OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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/kernel_binary_flowgraph.h" | 5 #include "vm/kernel_binary_flowgraph.h" |
6 | 6 |
| 7 #include "vm/compiler.h" |
7 #include "vm/longjump.h" | 8 #include "vm/longjump.h" |
8 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
9 | 10 |
10 #if !defined(DART_PRECOMPILED_RUNTIME) | 11 #if !defined(DART_PRECOMPILED_RUNTIME) |
11 | 12 |
12 namespace dart { | 13 namespace dart { |
13 namespace kernel { | 14 namespace kernel { |
14 | 15 |
15 #define Z (zone_) | 16 #define Z (zone_) |
16 #define H (translation_helper_) | 17 #define H (translation_helper_) |
(...skipping 30 matching lines...) Expand all Loading... |
47 H.SetStringOffsets(TypedData::Handle(Z, script.kernel_string_offsets())); | 48 H.SetStringOffsets(TypedData::Handle(Z, script.kernel_string_offsets())); |
48 H.SetStringData(TypedData::Handle(Z, script.kernel_string_data())); | 49 H.SetStringData(TypedData::Handle(Z, script.kernel_string_data())); |
49 H.SetCanonicalNames(TypedData::Handle(Z, script.kernel_canonical_names())); | 50 H.SetCanonicalNames(TypedData::Handle(Z, script.kernel_canonical_names())); |
50 type_translator_.active_class_ = &active_class_; | 51 type_translator_.active_class_ = &active_class_; |
51 } | 52 } |
52 | 53 |
53 StreamingScopeBuilder::~StreamingScopeBuilder() { | 54 StreamingScopeBuilder::~StreamingScopeBuilder() { |
54 delete builder_; | 55 delete builder_; |
55 } | 56 } |
56 | 57 |
57 void StreamingScopeBuilder::DiscoverEnclosingElements( | |
58 Zone* zone, | |
59 const Function& function, | |
60 Function* outermost_function, | |
61 intptr_t* outermost_kernel_offset, | |
62 intptr_t* parent_class_offset) { | |
63 // Find out if there is an enclosing kernel class (which will be used to | |
64 // resolve type parameters). | |
65 *outermost_function = function.raw(); | |
66 while (outermost_function->parent_function() != Object::null()) { | |
67 *outermost_function = outermost_function->parent_function(); | |
68 } | |
69 | |
70 if (outermost_function->kernel_function() != NULL) { | |
71 *outermost_kernel_offset = | |
72 static_cast<TreeNode*>(outermost_function->kernel_function()) | |
73 ->kernel_offset(); | |
74 *parent_class_offset = GetParentOffset(*outermost_kernel_offset); | |
75 } | |
76 } | |
77 | |
78 ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() { | 58 ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() { |
79 if (result_ != NULL) return result_; | 59 if (result_ != NULL) return result_; |
80 | 60 |
81 ASSERT(scope_ == NULL && depth_.loop_ == 0 && depth_.function_ == 0); | 61 ASSERT(scope_ == NULL && depth_.loop_ == 0 && depth_.function_ == 0); |
82 result_ = new (Z) ScopeBuildingResult(); | 62 result_ = new (Z) ScopeBuildingResult(); |
83 | 63 |
84 ParsedFunction* parsed_function = parsed_function_; | 64 ParsedFunction* parsed_function = parsed_function_; |
85 const Function& function = parsed_function->function(); | 65 const Function& function = parsed_function->function(); |
86 | 66 |
87 // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used | 67 // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used |
88 // e.g. for type translation. | 68 // e.g. for type translation. |
89 const dart::Class& klass = | 69 const dart::Class& klass = |
90 dart::Class::Handle(zone_, parsed_function_->function().Owner()); | 70 dart::Class::Handle(zone_, parsed_function_->function().Owner()); |
91 Function& outermost_function = Function::Handle(Z); | 71 Function& outermost_function = Function::Handle(Z); |
92 intptr_t outermost_kernel_offset = -1; | 72 intptr_t outermost_kernel_offset = -1; |
93 intptr_t parent_class_offset = -1; | 73 intptr_t parent_class_offset = -1; |
94 DiscoverEnclosingElements(Z, function, &outermost_function, | 74 builder_->DiscoverEnclosingElements(Z, function, &outermost_function, |
95 &outermost_kernel_offset, &parent_class_offset); | 75 &outermost_kernel_offset, |
| 76 &parent_class_offset); |
96 // Use [klass]/[kernel_class] as active class. Type parameters will get | 77 // Use [klass]/[kernel_class] as active class. Type parameters will get |
97 // resolved via [kernel_class] unless we are nested inside a static factory | 78 // resolved via [kernel_class] unless we are nested inside a static factory |
98 // in which case we will use [member]. | 79 // in which case we will use [member]. |
99 intptr_t class_type_parameters = 0; | 80 intptr_t class_type_parameters = 0; |
100 intptr_t class_type_parameters_offset_start = -1; | 81 intptr_t class_type_parameters_offset_start = -1; |
101 if (parent_class_offset > 0) { | 82 if (parent_class_offset > 0) { |
102 GetTypeParameterInfoForClass(parent_class_offset, &class_type_parameters, | 83 builder_->GetTypeParameterInfoForClass(parent_class_offset, |
103 &class_type_parameters_offset_start); | 84 &class_type_parameters, |
| 85 &class_type_parameters_offset_start); |
104 } | 86 } |
105 ActiveClassScope active_class_scope(&active_class_, class_type_parameters, | 87 ActiveClassScope active_class_scope(&active_class_, class_type_parameters, |
106 class_type_parameters_offset_start, | 88 class_type_parameters_offset_start, |
107 &klass); | 89 &klass); |
108 | 90 |
109 bool member_is_procedure = false; | 91 bool member_is_procedure = false; |
110 bool is_factory_procedure = false; | 92 bool is_factory_procedure = false; |
111 intptr_t member_type_parameters = 0; | 93 intptr_t member_type_parameters = 0; |
112 intptr_t member_type_parameters_offset_start = -1; | 94 intptr_t member_type_parameters_offset_start = -1; |
113 GetTypeParameterInfoForPossibleProcedure( | 95 builder_->GetTypeParameterInfoForPossibleProcedure( |
114 outermost_kernel_offset, &member_is_procedure, &is_factory_procedure, | 96 outermost_kernel_offset, &member_is_procedure, &is_factory_procedure, |
115 &member_type_parameters, &member_type_parameters_offset_start); | 97 &member_type_parameters, &member_type_parameters_offset_start); |
116 | 98 |
117 ActiveMemberScope active_member(&active_class_, member_is_procedure, | 99 ActiveMemberScope active_member(&active_class_, member_is_procedure, |
118 is_factory_procedure, member_type_parameters, | 100 is_factory_procedure, member_type_parameters, |
119 member_type_parameters_offset_start); | 101 member_type_parameters_offset_start); |
120 | 102 |
121 LocalScope* enclosing_scope = NULL; | 103 LocalScope* enclosing_scope = NULL; |
122 if (function.IsLocalFunction()) { | 104 if (function.IsLocalFunction()) { |
123 enclosing_scope = LocalScope::RestoreOuterScope( | 105 enclosing_scope = LocalScope::RestoreOuterScope( |
(...skipping 13 matching lines...) Expand all Loading... |
137 intptr_t parent_offset = -1; | 119 intptr_t parent_offset = -1; |
138 builder_->SetOffset(kernel_offset_); | 120 builder_->SetOffset(kernel_offset_); |
139 | 121 |
140 switch (function.kind()) { | 122 switch (function.kind()) { |
141 case RawFunction::kClosureFunction: | 123 case RawFunction::kClosureFunction: |
142 case RawFunction::kRegularFunction: | 124 case RawFunction::kRegularFunction: |
143 case RawFunction::kGetterFunction: | 125 case RawFunction::kGetterFunction: |
144 case RawFunction::kSetterFunction: | 126 case RawFunction::kSetterFunction: |
145 case RawFunction::kConstructor: { | 127 case RawFunction::kConstructor: { |
146 const Tag tag = builder_->PeekTag(); | 128 const Tag tag = builder_->PeekTag(); |
147 if (tag == kProcedure) { | 129 parent_offset = builder_->ReadUntilFunctionNode(); |
148 Tag has_function_node = ReadProcedureUntilFunctionNode( | |
149 &unused_word, &unused_intptr); // read first part of procedure. | |
150 if (has_function_node == kNothing) { | |
151 // Running a procedure without a function node doesn't make sense. | |
152 UNREACHABLE(); | |
153 } | |
154 // Now at start of FunctionNode. | |
155 } else if (tag == kConstructor) { | |
156 // read first part of constructor. | |
157 parent_offset = ReadConstructorUntilFunctionNode(); | |
158 // Now at start of FunctionNode. | |
159 // Notice that we also have a list of initializers after that! | |
160 } else if (tag == kFunctionNode) { | |
161 // Already at start of FunctionNode. | |
162 } else { | |
163 UNREACHABLE(); | |
164 } | |
165 word async_marker_word; | 130 word async_marker_word; |
166 ReadFunctionNodeUntilTypeParameters( | 131 builder_->ReadFunctionNodeUntilTypeParameters( |
167 &async_marker_word, | 132 &unused_tokenposition, &unused_tokenposition, &async_marker_word, |
168 &unused_word); // read first part of function node. | 133 &unused_word); // read first part of function node. |
169 current_function_async_marker_ = | 134 current_function_async_marker_ = |
170 static_cast<FunctionNode::AsyncMarker>(async_marker_word); | 135 static_cast<FunctionNode::AsyncMarker>(async_marker_word); |
171 // NOTE: FunctionNode is not read entirely yet! It continues below the if. | 136 // NOTE: FunctionNode is not read entirely yet! It continues below the if. |
172 | 137 |
173 intptr_t pos = 0; | 138 intptr_t pos = 0; |
174 if (function.IsClosureFunction()) { | 139 if (function.IsClosureFunction()) { |
175 LocalVariable* variable = MakeVariable( | 140 LocalVariable* variable = MakeVariable( |
176 TokenPosition::kNoSource, TokenPosition::kNoSource, | 141 TokenPosition::kNoSource, TokenPosition::kNoSource, |
177 Symbols::ClosureParameter(), AbstractType::dynamic_type()); | 142 Symbols::ClosureParameter(), AbstractType::dynamic_type()); |
178 variable->set_is_forced_stack(); | 143 variable->set_is_forced_stack(); |
179 scope_->InsertParameterAt(pos++, variable); | 144 scope_->InsertParameterAt(pos++, variable); |
180 } else if (!function.is_static()) { | 145 } else if (!function.is_static()) { |
181 // We use [is_static] instead of [IsStaticFunction] because the latter | 146 // We use [is_static] instead of [IsStaticFunction] because the latter |
182 // returns `false` for constructors. | 147 // returns `false` for constructors. |
183 dart::Class& klass = dart::Class::Handle(Z, function.Owner()); | 148 dart::Class& klass = dart::Class::Handle(Z, function.Owner()); |
184 Type& klass_type = H.GetCanonicalType(klass); | 149 Type& klass_type = H.GetCanonicalType(klass); |
185 LocalVariable* variable = | 150 LocalVariable* variable = |
186 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, | 151 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
187 Symbols::This(), klass_type); | 152 Symbols::This(), klass_type); |
188 scope_->InsertParameterAt(pos++, variable); | 153 scope_->InsertParameterAt(pos++, variable); |
189 result_->this_variable = variable; | 154 result_->this_variable = variable; |
190 | 155 |
191 // We visit instance field initializers because they might contain | 156 // We visit instance field initializers because they might contain |
192 // [Let] expressions and we need to have a mapping. | 157 // [Let] expressions and we need to have a mapping. |
193 if (tag == kConstructor) { | 158 if (tag == kConstructor) { |
194 ASSERT(parent_offset >= 0); | 159 ASSERT(parent_offset >= 0); |
195 AlternativeReadingScope alt(builder_->reader_, parent_offset); | 160 AlternativeReadingScope alt(builder_->reader_, parent_offset); |
196 ReadClassUntilFields(); // read first part of class. | 161 builder_->ReadClassUntilFields(); // read first part of class. |
197 intptr_t list_length = | 162 intptr_t list_length = |
198 builder_->ReadListLength(); // read fields list length. | 163 builder_->ReadListLength(); // read fields list length. |
199 for (intptr_t i = 0; i < list_length; i++) { | 164 for (intptr_t i = 0; i < list_length; i++) { |
200 intptr_t field_offset = builder_->ReaderOffset(); | 165 intptr_t field_offset = builder_->ReaderOffset(); |
201 TokenPosition position; | 166 TokenPosition position; |
202 TokenPosition end_position; | 167 TokenPosition end_position; |
203 word flags; | 168 word flags; |
204 ReadFieldUntilAnnotation(&position, &end_position, &flags, | 169 builder_->ReadFieldUntilAnnotation(&unused_nameindex, &position, |
205 &unused_intptr); | 170 &end_position, &flags, |
| 171 &unused_intptr); |
206 bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic; | 172 bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic; |
207 builder_->SkipListOfExpressions(); // read annotations. | 173 builder_->SkipListOfExpressions(); // read annotations. |
208 builder_->SkipDartType(); // read type. | 174 builder_->SkipDartType(); // read type. |
209 Tag initializer_tag = builder_->ReadTag(); | 175 Tag initializer_tag = |
| 176 builder_->ReadTag(); // read first part of initializer. |
210 if (!is_static && initializer_tag == kSomething) { | 177 if (!is_static && initializer_tag == kSomething) { |
211 EnterScope(field_offset); | 178 EnterScope(field_offset); |
212 VisitExpression(); // read initializer. | 179 VisitExpression(); // read initializer. |
213 ExitScope(position, end_position); | 180 ExitScope(position, end_position); |
214 } else if (initializer_tag == kSomething) { | 181 } else if (initializer_tag == kSomething) { |
215 builder_->SkipExpression(); // read initializer. | 182 builder_->SkipExpression(); // read initializer. |
216 } | 183 } |
217 } | 184 } |
218 } | 185 } |
219 } else if (function.IsFactory()) { | 186 } else if (function.IsFactory()) { |
220 LocalVariable* variable = MakeVariable( | 187 LocalVariable* variable = MakeVariable( |
221 TokenPosition::kNoSource, TokenPosition::kNoSource, | 188 TokenPosition::kNoSource, TokenPosition::kNoSource, |
222 Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type()); | 189 Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type()); |
223 scope_->InsertParameterAt(pos++, variable); | 190 scope_->InsertParameterAt(pos++, variable); |
224 result_->type_arguments_variable = variable; | 191 result_->type_arguments_variable = variable; |
225 } | 192 } |
226 | 193 |
227 // Continue reading FunctionNode. | 194 // Continue reading FunctionNode. |
228 builder_->SkipTypeParametersList(); // read type_parameters. | 195 builder_->SkipTypeParametersList(); // read type_parameters. |
229 builder_->ReadUInt(); // read required_parameter_count. | 196 builder_->ReadUInt(); // read required_parameter_count. |
| 197 builder_->ReadUInt(); // read total parameter count. |
230 AddPositionalAndNamedParameters( | 198 AddPositionalAndNamedParameters( |
231 pos); // read positional_parameters and named_parameters. | 199 pos); // read positional_parameters and named_parameters. |
232 | 200 |
233 // We generate a syntethic body for implicit closure functions - which | 201 // We generate a syntethic body for implicit closure functions - which |
234 // will forward the call to the real function. | 202 // will forward the call to the real function. |
235 // -> see BuildGraphOfImplicitClosureFunction | 203 // -> see BuildGraphOfImplicitClosureFunction |
236 if (!function.IsImplicitClosureFunction()) { | 204 if (!function.IsImplicitClosureFunction()) { |
237 builder_->SetOffset(kernel_offset_); | 205 builder_->SetOffset(kernel_offset_); |
238 first_body_token_position_ = TokenPosition::kNoSource; | 206 first_body_token_position_ = TokenPosition::kNoSource; |
239 VisitNode(); | 207 VisitNode(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 UNREACHABLE(); | 280 UNREACHABLE(); |
313 } | 281 } |
314 if (needs_expr_temp_) { | 282 if (needs_expr_temp_) { |
315 scope_->AddVariable(parsed_function_->EnsureExpressionTemp()); | 283 scope_->AddVariable(parsed_function_->EnsureExpressionTemp()); |
316 } | 284 } |
317 parsed_function->AllocateVariables(); | 285 parsed_function->AllocateVariables(); |
318 | 286 |
319 return result_; | 287 return result_; |
320 } | 288 } |
321 | 289 |
322 intptr_t StreamingScopeBuilder::GetParentOffset(intptr_t offset) { | |
323 AlternativeReadingScope alt(builder_->reader_, offset); | |
324 | |
325 Tag tag = builder_->PeekTag(); | |
326 intptr_t parent_offset = -1; | |
327 switch (tag) { | |
328 case kConstructor: | |
329 return ReadConstructorUntilFunctionNode(); | |
330 case kProcedure: | |
331 ReadProcedureUntilFunctionNode( | |
332 &unused_word, &parent_offset); // read first part of procedure. | |
333 return parent_offset; | |
334 case kField: | |
335 ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition, | |
336 &unused_word, &parent_offset); | |
337 return parent_offset; | |
338 default: | |
339 UNIMPLEMENTED(); | |
340 return -1; | |
341 } | |
342 } | |
343 | |
344 void StreamingScopeBuilder::GetTypeParameterInfoForClass( | |
345 intptr_t class_offset, | |
346 intptr_t* type_paremeter_counts, | |
347 intptr_t* type_paremeter_offset) { | |
348 AlternativeReadingScope alt(builder_->reader_, class_offset); | |
349 | |
350 ReadClassUntilTypeParameters(); | |
351 *type_paremeter_counts = | |
352 builder_->ReadListLength(); // read type_parameters list length. | |
353 *type_paremeter_offset = builder_->ReaderOffset(); | |
354 } | |
355 | |
356 void StreamingScopeBuilder::VisitNode() { | 290 void StreamingScopeBuilder::VisitNode() { |
357 Tag tag = builder_->PeekTag(); | 291 Tag tag = builder_->PeekTag(); |
358 switch (tag) { | 292 switch (tag) { |
359 case kConstructor: | 293 case kConstructor: |
360 VisitConstructor(); | 294 VisitConstructor(); |
361 return; | 295 return; |
362 case kProcedure: | 296 case kProcedure: |
363 VisitProcedure(); | 297 VisitProcedure(); |
364 return; | 298 return; |
365 case kField: | 299 case kField: |
366 VisitField(); | 300 VisitField(); |
367 return; | 301 return; |
368 case kFunctionNode: | 302 case kFunctionNode: |
369 VisitFunctionNode(); | 303 VisitFunctionNode(); |
370 return; | 304 return; |
371 default: | 305 default: |
372 UNIMPLEMENTED(); | 306 UNIMPLEMENTED(); |
373 return; | 307 return; |
374 } | 308 } |
375 } | 309 } |
376 | 310 |
377 intptr_t StreamingScopeBuilder::ReadConstructorUntilFunctionNode() { | |
378 Tag tag = builder_->ReadTag(); | |
379 ASSERT(tag == kConstructor); | |
380 builder_->SkipCanonicalNameReference(); // read canonical name reference. | |
381 builder_->ReadPosition(); // read position. | |
382 builder_->ReadPosition(); // read end position. | |
383 builder_->ReadFlags(); // read flags. | |
384 intptr_t parent_offset = builder_->ReadUInt(); // parent class binary offset. | |
385 builder_->SkipName(); // read name. | |
386 builder_->SkipListOfExpressions(); // read annotations. | |
387 return parent_offset; | |
388 } | |
389 | |
390 void StreamingScopeBuilder::VisitConstructor() { | 311 void StreamingScopeBuilder::VisitConstructor() { |
391 // Field initializers that come from non-static field declarations are | 312 // Field initializers that come from non-static field declarations are |
392 // compiled as if they appear in the constructor initializer list. This is | 313 // compiled as if they appear in the constructor initializer list. This is |
393 // important for closure-valued field initializers because the VM expects the | 314 // important for closure-valued field initializers because the VM expects the |
394 // corresponding closure functions to appear as if they were nested inside the | 315 // corresponding closure functions to appear as if they were nested inside the |
395 // constructor. | 316 // constructor. |
396 intptr_t parent_offset = ReadConstructorUntilFunctionNode(); | 317 intptr_t parent_offset = builder_->ReadConstructorUntilFunctionNode(); |
397 ASSERT(parent_offset >= 0); | 318 ASSERT(parent_offset >= 0); |
398 { | 319 { |
399 AlternativeReadingScope alt(builder_->reader_, parent_offset); | 320 AlternativeReadingScope alt(builder_->reader_, parent_offset); |
400 ReadClassUntilFields(); // read first part of class. | 321 builder_->ReadClassUntilFields(); // read first part of class. |
401 | 322 |
402 intptr_t list_length = | 323 intptr_t list_length = |
403 builder_->ReadListLength(); // read fields list length. | 324 builder_->ReadListLength(); // read fields list length. |
404 for (intptr_t i = 0; i < list_length; i++) { | 325 for (intptr_t i = 0; i < list_length; i++) { |
405 word flags; | 326 word flags; |
406 ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition, | 327 builder_->ReadFieldUntilAnnotation( |
407 &flags, &unused_intptr); | 328 &unused_nameindex, &unused_tokenposition, &unused_tokenposition, |
| 329 &flags, &unused_intptr); |
408 bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic; | 330 bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic; |
409 builder_->SkipListOfExpressions(); // read annotations. | 331 builder_->SkipListOfExpressions(); // read annotations. |
410 builder_->SkipDartType(); // read type. | 332 builder_->SkipDartType(); // read type. |
411 Tag initializer_tag = builder_->ReadTag(); | 333 Tag initializer_tag = builder_->ReadTag(); |
412 if (!is_static && initializer_tag == kSomething) { | 334 if (!is_static && initializer_tag == kSomething) { |
413 VisitExpression(); // read initializer. | 335 VisitExpression(); // read initializer. |
414 } else if (initializer_tag == kSomething) { | 336 } else if (initializer_tag == kSomething) { |
415 builder_->SkipExpression(); // read initializer. | 337 builder_->SkipExpression(); // read initializer. |
416 } | 338 } |
417 } | 339 } |
418 } | 340 } |
419 | 341 |
420 // Visit children (note that there's no reason to visit the name). | 342 // Visit children (note that there's no reason to visit the name). |
421 VisitFunctionNode(); | 343 VisitFunctionNode(); |
422 intptr_t list_length = | 344 intptr_t list_length = |
423 builder_->ReadListLength(); // read initializers list length. | 345 builder_->ReadListLength(); // read initializers list length. |
424 for (intptr_t i = 0; i < list_length; i++) { | 346 for (intptr_t i = 0; i < list_length; i++) { |
425 VisitInitializer(); | 347 VisitInitializer(); |
426 } | 348 } |
427 } | 349 } |
428 | 350 |
429 void StreamingScopeBuilder::VisitProcedure() { | 351 void StreamingScopeBuilder::VisitProcedure() { |
430 Tag function_node = ReadProcedureUntilFunctionNode( | 352 Tag function_node = builder_->ReadProcedureUntilFunctionNode( |
431 &unused_word, &unused_intptr); // read first part of procedure. | 353 &unused_word, &unused_intptr); // read first part of procedure. |
432 if (function_node == kSomething) { | 354 if (function_node == kSomething) { |
433 VisitFunctionNode(); | 355 VisitFunctionNode(); |
434 } | 356 } |
435 } | 357 } |
436 | 358 |
437 void StreamingScopeBuilder::ReadFieldUntilAnnotation( | |
438 TokenPosition* position, | |
439 TokenPosition* end_position, | |
440 word* flags, | |
441 intptr_t* parent_offset) { | |
442 Tag tag = builder_->ReadTag(); | |
443 ASSERT(tag == kField); | |
444 | |
445 builder_->SkipCanonicalNameReference(); // read canonical_name. | |
446 *position = builder_->ReadPosition(); // read position. | |
447 *end_position = builder_->ReadPosition(); // read end position. | |
448 *flags = builder_->ReadFlags(); // read flags. | |
449 *parent_offset = builder_->ReadUInt(); // read parent class binary offset. | |
450 builder_->SkipName(); // read name. | |
451 builder_->ReadUInt(); // source_uri_index. | |
452 } | |
453 | |
454 void StreamingScopeBuilder::VisitField() { | 359 void StreamingScopeBuilder::VisitField() { |
455 ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition, | 360 builder_->ReadFieldUntilAnnotation( |
456 &unused_intptr, | 361 &unused_nameindex, &unused_tokenposition, &unused_tokenposition, |
457 &unused_word); // read first part of field. | 362 &unused_intptr, &unused_word); // read first part of field. |
458 builder_->SkipListOfExpressions(); // read annotations. | 363 builder_->SkipListOfExpressions(); // read annotations. |
459 VisitDartType(); // read type. | 364 VisitDartType(); // read type. |
460 Tag tag = builder_->ReadTag(); // read initializer (part 1). | 365 Tag tag = builder_->ReadTag(); // read initializer (part 1). |
461 if (tag == kSomething) { | 366 if (tag == kSomething) { |
462 VisitExpression(); // read initializer (part 2). | 367 VisitExpression(); // read initializer (part 2). |
463 } | 368 } |
464 } | 369 } |
465 | 370 |
466 Tag StreamingScopeBuilder::ReadProcedureUntilFunctionNode( | |
467 word* kind, | |
468 intptr_t* parent_offset) { | |
469 Tag tag = builder_->ReadTag(); // read tag. | |
470 ASSERT(tag == kProcedure); | |
471 builder_->SkipCanonicalNameReference(); // read canonical name reference. | |
472 builder_->ReadPosition(); // read position. | |
473 builder_->ReadPosition(); // read end position. | |
474 *kind = builder_->ReadByte(); // read kind. | |
475 builder_->ReadFlags(); // read flags. | |
476 *parent_offset = builder_->ReadUInt(); // read parent class binary offset. | |
477 builder_->SkipName(); // read name, | |
478 builder_->ReadUInt(); // read source_uri_index. | |
479 builder_->SkipListOfExpressions(); // read annotations. | |
480 return builder_->ReadTag(); // read tag for optional function node. | |
481 } | |
482 | |
483 void StreamingScopeBuilder::GetTypeParameterInfoForPossibleProcedure( | |
484 intptr_t outermost_kernel_offset, | |
485 bool* member_is_procedure, | |
486 bool* is_factory_procedure, | |
487 intptr_t* member_type_parameters, | |
488 intptr_t* member_type_parameters_offset_start) { | |
489 if (outermost_kernel_offset >= 0) { | |
490 AlternativeReadingScope alt(builder_->reader_, outermost_kernel_offset); | |
491 Tag tag = builder_->PeekTag(); | |
492 if (tag == kProcedure) { | |
493 *member_is_procedure = true; | |
494 | |
495 word kind; | |
496 tag = ReadProcedureUntilFunctionNode( | |
497 &kind, &unused_intptr); // read first part of procedure. | |
498 *is_factory_procedure = | |
499 static_cast<Procedure::ProcedureKind>(kind) == Procedure::kFactory; | |
500 | |
501 if (tag == kSomething) { | |
502 ReadFunctionNodeUntilTypeParameters( | |
503 &unused_word, &unused_word); // read first part of function node. | |
504 | |
505 intptr_t list_length = | |
506 builder_->ReadListLength(); // read type_parameters list length. | |
507 if (list_length > 0) { | |
508 *member_type_parameters = list_length; | |
509 *member_type_parameters_offset_start = builder_->ReaderOffset(); | |
510 } | |
511 } | |
512 } | |
513 } | |
514 } | |
515 | |
516 void StreamingScopeBuilder::ReadClassUntilTypeParameters() { | |
517 Tag class_tag = builder_->ReadTag(); | |
518 ASSERT(class_tag == kClass); | |
519 builder_->SkipCanonicalNameReference(); // read canonical_name. | |
520 builder_->ReadPosition(); // read position. | |
521 builder_->ReadBool(); // read is_abstract. | |
522 builder_->SkipStringReference(); // read name index. | |
523 builder_->ReadUInt(); // read source_uri_index. | |
524 builder_->SkipListOfExpressions(); // read annotations. | |
525 } | |
526 | |
527 void StreamingScopeBuilder::ReadClassUntilFields() { | |
528 ReadClassUntilTypeParameters(); | |
529 builder_->SkipTypeParametersList(); // read type_parameters. | |
530 Tag type_tag = builder_->ReadTag(); // read type (part 1). | |
531 if (type_tag == kSomething) { | |
532 builder_->SkipDartType(); // read type (part 2). | |
533 } | |
534 type_tag = builder_->ReadTag(); // read Mixed-in type (part 1). | |
535 if (type_tag == kSomething) { | |
536 builder_->SkipDartType(); // read Mixed-in type (part 2). | |
537 } | |
538 builder_->SkipListOfDartTypes(); // read implemented_classes. | |
539 } | |
540 | |
541 void StreamingScopeBuilder::ReadFunctionNodeUntilTypeParameters( | |
542 word* async_marker, | |
543 word* dart_async_marker) { | |
544 Tag tag = builder_->ReadTag(); // read tag. | |
545 ASSERT(tag == kFunctionNode); | |
546 | |
547 builder_->ReadPosition(); // read position. | |
548 builder_->ReadPosition(); // read end position. | |
549 *async_marker = builder_->ReadByte(); // read async marker. | |
550 *dart_async_marker = builder_->ReadByte(); // read dart async marker. | |
551 } | |
552 | |
553 void StreamingScopeBuilder::VisitFunctionNode() { | 371 void StreamingScopeBuilder::VisitFunctionNode() { |
554 word async_marker_word; | 372 word async_marker_word; |
555 word dart_async_marker_word; | 373 word dart_async_marker_word; |
556 ReadFunctionNodeUntilTypeParameters(&async_marker_word, | 374 builder_->ReadFunctionNodeUntilTypeParameters( |
557 &dart_async_marker_word); | 375 &unused_tokenposition, &unused_tokenposition, &async_marker_word, |
| 376 &dart_async_marker_word); |
558 FunctionNode::AsyncMarker async_marker = | 377 FunctionNode::AsyncMarker async_marker = |
559 static_cast<FunctionNode::AsyncMarker>(async_marker_word); | 378 static_cast<FunctionNode::AsyncMarker>(async_marker_word); |
560 FunctionNode::AsyncMarker dart_async_marker = | 379 FunctionNode::AsyncMarker dart_async_marker = |
561 static_cast<FunctionNode::AsyncMarker>(dart_async_marker_word); | 380 static_cast<FunctionNode::AsyncMarker>(dart_async_marker_word); |
562 | 381 |
563 intptr_t list_length = | 382 intptr_t list_length = |
564 builder_->ReadListLength(); // read type_parameters list length. | 383 builder_->ReadListLength(); // read type_parameters list length. |
565 for (intptr_t i = 0; i < list_length; ++i) { | 384 for (intptr_t i = 0; i < list_length; ++i) { |
566 builder_->SkipStringReference(); // read ith name index. | 385 builder_->SkipStringReference(); // read ith name index. |
567 VisitDartType(); // read ith bound. | 386 VisitDartType(); // read ith bound. |
(...skipping 15 matching lines...) Expand all Loading... |
583 i < parsed_function_->function().NumOptionalPositionalParameters(); | 402 i < parsed_function_->function().NumOptionalPositionalParameters(); |
584 i++) { | 403 i++) { |
585 scope->VariableAt(offset + i)->set_is_forced_stack(); | 404 scope->VariableAt(offset + i)->set_is_forced_stack(); |
586 } | 405 } |
587 } | 406 } |
588 | 407 |
589 // Read (but don't visit) the positional and named parameters, because they've | 408 // Read (but don't visit) the positional and named parameters, because they've |
590 // already been added to the scope. | 409 // already been added to the scope. |
591 | 410 |
592 builder_->ReadUInt(); // read required_parameter_count. | 411 builder_->ReadUInt(); // read required_parameter_count. |
| 412 builder_->ReadUInt(); // read total parameter count. |
593 | 413 |
594 builder_->SkipListOfVariableDeclarations(); // read list of positionals. | 414 builder_->SkipListOfVariableDeclarations(); // read list of positionals. |
595 builder_->SkipListOfVariableDeclarations(); // read list of named. | 415 builder_->SkipListOfVariableDeclarations(); // read list of named. |
596 builder_->SkipDartType(); // read return type. | 416 builder_->SkipDartType(); // read return type. |
597 | 417 |
598 if (builder_->ReadTag() == kSomething) { | 418 if (builder_->ReadTag() == kSomething) { |
599 PositionScope scope(builder_->reader_); | 419 PositionScope scope(builder_->reader_); |
600 VisitStatement(); // Read body | 420 VisitStatement(); // Read body |
601 first_body_token_position_ = builder_->reader_->min_position(); | 421 first_body_token_position_ = builder_->reader_->min_position(); |
602 } | 422 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
636 void StreamingScopeBuilder::VisitInitializer() { | 456 void StreamingScopeBuilder::VisitInitializer() { |
637 Tag tag = builder_->ReadTag(); | 457 Tag tag = builder_->ReadTag(); |
638 switch (tag) { | 458 switch (tag) { |
639 case kInvalidInitializer: | 459 case kInvalidInitializer: |
640 return; | 460 return; |
641 case kFieldInitializer: | 461 case kFieldInitializer: |
642 builder_->SkipCanonicalNameReference(); // read field_reference. | 462 builder_->SkipCanonicalNameReference(); // read field_reference. |
643 VisitExpression(); // read value. | 463 VisitExpression(); // read value. |
644 return; | 464 return; |
645 case kSuperInitializer: | 465 case kSuperInitializer: |
646 builder_->SkipCanonicalNameReference(); // read field_reference. | 466 builder_->SkipCanonicalNameReference(); // read target_reference. |
647 VisitArguments(); // read arguments. | 467 VisitArguments(); // read arguments. |
648 return; | 468 return; |
649 case kRedirectingInitializer: | 469 case kRedirectingInitializer: |
650 builder_->SkipCanonicalNameReference(); // read field_reference. | 470 builder_->SkipCanonicalNameReference(); // read target_reference. |
651 VisitArguments(); // read arguments. | 471 VisitArguments(); // read arguments. |
652 return; | 472 return; |
653 case kLocalInitializer: | 473 case kLocalInitializer: |
654 VisitVariableDeclaration(); // read variable. | 474 VisitVariableDeclaration(); // read variable. |
655 return; | 475 return; |
656 default: | 476 default: |
657 UNREACHABLE(); | 477 UNREACHABLE(); |
658 } | 478 } |
659 } | 479 } |
660 | 480 |
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1314 depth_ = DepthState(depth_.function_ + 1); | 1134 depth_ = DepthState(depth_.function_ + 1); |
1315 EnterScope(parent_kernel_offset); | 1135 EnterScope(parent_kernel_offset); |
1316 current_function_scope_ = scope_; | 1136 current_function_scope_ = scope_; |
1317 current_function_async_marker_ = async_marker; | 1137 current_function_async_marker_ = async_marker; |
1318 if (depth_.function_ == 1) { | 1138 if (depth_.function_ == 1) { |
1319 FunctionScope function_scope = {offset, scope_}; | 1139 FunctionScope function_scope = {offset, scope_}; |
1320 result_->function_scopes.Add(function_scope); | 1140 result_->function_scopes.Add(function_scope); |
1321 } | 1141 } |
1322 | 1142 |
1323 builder_->ReadUInt(); // read required_parameter_count. | 1143 builder_->ReadUInt(); // read required_parameter_count. |
| 1144 builder_->ReadUInt(); // read total parameter count. |
1324 // read positional_parameters and named_parameters. | 1145 // read positional_parameters and named_parameters. |
1325 AddPositionalAndNamedParameters(); | 1146 AddPositionalAndNamedParameters(); |
1326 | 1147 |
1327 // "Peek" is now done. | 1148 // "Peek" is now done. |
1328 builder_->SetOffset(offset); | 1149 builder_->SetOffset(offset); |
1329 | 1150 |
1330 VisitFunctionNode(); // read function node. | 1151 VisitFunctionNode(); // read function node. |
1331 | 1152 |
1332 ExitScope(position, end_position); | 1153 ExitScope(position, end_position); |
1333 depth_ = saved_depth_state; | 1154 depth_ = saved_depth_state; |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1474 if ((depth_.function_ == 0) && (result_->switch_variable == NULL)) { | 1295 if ((depth_.function_ == 0) && (result_->switch_variable == NULL)) { |
1475 LocalVariable* variable = | 1296 LocalVariable* variable = |
1476 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, | 1297 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
1477 Symbols::SwitchExpr(), AbstractType::dynamic_type()); | 1298 Symbols::SwitchExpr(), AbstractType::dynamic_type()); |
1478 variable->set_is_forced_stack(); | 1299 variable->set_is_forced_stack(); |
1479 current_function_scope_->AddVariable(variable); | 1300 current_function_scope_->AddVariable(variable); |
1480 result_->switch_variable = variable; | 1301 result_->switch_variable = variable; |
1481 } | 1302 } |
1482 } | 1303 } |
1483 | 1304 |
1484 StringIndex StreamingScopeBuilder::GetNameFromVariableDeclaration( | |
1485 intptr_t kernel_offset) { | |
1486 // Temporarily go to the variable declaration, read the name. | |
1487 AlternativeReadingScope alt(builder_->reader_, kernel_offset); | |
1488 builder_->ReadPosition(); // read position. | |
1489 builder_->ReadPosition(); // read equals position. | |
1490 builder_->ReadFlags(); // read flags. | |
1491 return builder_->ReadStringReference(); // read name index. | |
1492 } | |
1493 | |
1494 void StreamingScopeBuilder::LookupVariable(intptr_t declaration_binary_offest) { | 1305 void StreamingScopeBuilder::LookupVariable(intptr_t declaration_binary_offest) { |
1495 LocalVariable* variable = result_->locals.Lookup(declaration_binary_offest); | 1306 LocalVariable* variable = result_->locals.Lookup(declaration_binary_offest); |
1496 if (variable == NULL) { | 1307 if (variable == NULL) { |
1497 // We have not seen a declaration of the variable, so it must be the | 1308 // We have not seen a declaration of the variable, so it must be the |
1498 // case that we are compiling a nested function and the variable is | 1309 // case that we are compiling a nested function and the variable is |
1499 // declared in an outer scope. In that case, look it up in the scope by | 1310 // declared in an outer scope. In that case, look it up in the scope by |
1500 // name and add it to the variable map to simplify later lookup. | 1311 // name and add it to the variable map to simplify later lookup. |
1501 ASSERT(current_function_scope_->parent() != NULL); | 1312 ASSERT(current_function_scope_->parent() != NULL); |
1502 | 1313 |
1503 StringIndex var_name = | 1314 StringIndex var_name = |
1504 GetNameFromVariableDeclaration(declaration_binary_offest); | 1315 builder_->GetNameFromVariableDeclaration(declaration_binary_offest); |
1505 | 1316 |
1506 const dart::String& name = H.DartSymbol(var_name); | 1317 const dart::String& name = H.DartSymbol(var_name); |
1507 variable = current_function_scope_->parent()->LookupVariable(name, true); | 1318 variable = current_function_scope_->parent()->LookupVariable(name, true); |
1508 ASSERT(variable != NULL); | 1319 ASSERT(variable != NULL); |
1509 result_->locals.Insert(declaration_binary_offest, variable); | 1320 result_->locals.Insert(declaration_binary_offest, variable); |
1510 } | 1321 } |
1511 | 1322 |
1512 if (variable->owner()->function_level() < scope_->function_level()) { | 1323 if (variable->owner()->function_level() < scope_->function_level()) { |
1513 // We call `LocalScope->CaptureVariable(variable)` in two scenarios for two | 1324 // We call `LocalScope->CaptureVariable(variable)` in two scenarios for two |
1514 // different reasons: | 1325 // different reasons: |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1579 | 1390 |
1580 | 1391 |
1581 AbstractType& StreamingDartTypeTranslator::BuildType() { | 1392 AbstractType& StreamingDartTypeTranslator::BuildType() { |
1582 BuildTypeInternal(); | 1393 BuildTypeInternal(); |
1583 | 1394 |
1584 // We return a new `ZoneHandle` here on purpose: The intermediate language | 1395 // We return a new `ZoneHandle` here on purpose: The intermediate language |
1585 // instructions do not make a copy of the handle, so we do it. | 1396 // instructions do not make a copy of the handle, so we do it. |
1586 return dart::AbstractType::ZoneHandle(Z, result_.raw()); | 1397 return dart::AbstractType::ZoneHandle(Z, result_.raw()); |
1587 } | 1398 } |
1588 | 1399 |
| 1400 AbstractType& StreamingDartTypeTranslator::BuildTypeWithoutFinalization() { |
| 1401 bool saved_finalize = finalize_; |
| 1402 finalize_ = false; |
| 1403 BuildTypeInternal(); |
| 1404 finalize_ = saved_finalize; |
| 1405 |
| 1406 // We return a new `ZoneHandle` here on purpose: The intermediate language |
| 1407 // instructions do not make a copy of the handle, so we do it. |
| 1408 return dart::AbstractType::ZoneHandle(Z, result_.raw()); |
| 1409 } |
| 1410 |
1589 AbstractType& StreamingDartTypeTranslator::BuildVariableType() { | 1411 AbstractType& StreamingDartTypeTranslator::BuildVariableType() { |
1590 AbstractType& abstract_type = BuildType(); | 1412 AbstractType& abstract_type = BuildType(); |
1591 | 1413 |
1592 // We return a new `ZoneHandle` here on purpose: The intermediate language | 1414 // We return a new `ZoneHandle` here on purpose: The intermediate language |
1593 // instructions do not make a copy of the handle, so we do it. | 1415 // instructions do not make a copy of the handle, so we do it. |
1594 AbstractType& type = Type::ZoneHandle(Z); | 1416 AbstractType& type = Type::ZoneHandle(Z); |
1595 | 1417 |
1596 if (abstract_type.IsMalformed()) { | 1418 if (abstract_type.IsMalformed()) { |
1597 type = AbstractType::dynamic_type().raw(); | 1419 type = AbstractType::dynamic_type().raw(); |
1598 } else { | 1420 } else { |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2178 } else { | 2000 } else { |
2179 result_ = field.StaticValue(); | 2001 result_ = field.StaticValue(); |
2180 } | 2002 } |
2181 } else if (H.IsProcedure(target)) { | 2003 } else if (H.IsProcedure(target)) { |
2182 const Function& function = | 2004 const Function& function = |
2183 Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target)); | 2005 Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target)); |
2184 | 2006 |
2185 if (H.IsMethod(target)) { | 2007 if (H.IsMethod(target)) { |
2186 Function& closure_function = | 2008 Function& closure_function = |
2187 Function::ZoneHandle(Z, function.ImplicitClosureFunction()); | 2009 Function::ZoneHandle(Z, function.ImplicitClosureFunction()); |
2188 closure_function.set_kernel_function(function.kernel_function()); | |
2189 result_ = closure_function.ImplicitStaticClosure(); | 2010 result_ = closure_function.ImplicitStaticClosure(); |
2190 result_ = H.Canonicalize(result_); | 2011 result_ = H.Canonicalize(result_); |
2191 } else if (H.IsGetter(target)) { | 2012 } else if (H.IsGetter(target)) { |
2192 UNIMPLEMENTED(); | 2013 UNIMPLEMENTED(); |
2193 } else { | 2014 } else { |
2194 UNIMPLEMENTED(); | 2015 UNIMPLEMENTED(); |
2195 } | 2016 } |
2196 } | 2017 } |
2197 } | 2018 } |
2198 | 2019 |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2624 } | 2445 } |
2625 | 2446 |
2626 bool StreamingConstantEvaluator::EvaluateBooleanExpressionHere() { | 2447 bool StreamingConstantEvaluator::EvaluateBooleanExpressionHere() { |
2627 EvaluateExpression(builder_->ReaderOffset(), false); | 2448 EvaluateExpression(builder_->ReaderOffset(), false); |
2628 AssertBoolInCheckedMode(); | 2449 AssertBoolInCheckedMode(); |
2629 return result_.raw() == Bool::True().raw(); | 2450 return result_.raw() == Bool::True().raw(); |
2630 } | 2451 } |
2631 | 2452 |
2632 bool StreamingConstantEvaluator::GetCachedConstant(intptr_t kernel_offset, | 2453 bool StreamingConstantEvaluator::GetCachedConstant(intptr_t kernel_offset, |
2633 Instance* value) { | 2454 Instance* value) { |
2634 if (builder_ == NULL) return false; | 2455 if (builder_ == NULL || builder_->flow_graph_builder_ == NULL) return false; |
2635 | 2456 |
2636 const Function& function = builder_->parsed_function()->function(); | 2457 const Function& function = builder_->parsed_function()->function(); |
2637 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { | 2458 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { |
2638 // Don't cache constants in initializer expressions. They get | 2459 // Don't cache constants in initializer expressions. They get |
2639 // evaluated only once. | 2460 // evaluated only once. |
2640 return false; | 2461 return false; |
2641 } | 2462 } |
2642 | 2463 |
2643 bool is_present = false; | 2464 bool is_present = false; |
2644 ASSERT(!script_.InVMHeap()); | 2465 ASSERT(!script_.InVMHeap()); |
(...skipping 10 matching lines...) Expand all Loading... |
2655 ++H.thread()->compiler_stats()->num_const_cache_hits; | 2476 ++H.thread()->compiler_stats()->num_const_cache_hits; |
2656 } | 2477 } |
2657 return is_present; | 2478 return is_present; |
2658 } | 2479 } |
2659 | 2480 |
2660 | 2481 |
2661 void StreamingConstantEvaluator::CacheConstantValue(intptr_t kernel_offset, | 2482 void StreamingConstantEvaluator::CacheConstantValue(intptr_t kernel_offset, |
2662 const Instance& value) { | 2483 const Instance& value) { |
2663 ASSERT(Thread::Current()->IsMutatorThread()); | 2484 ASSERT(Thread::Current()->IsMutatorThread()); |
2664 | 2485 |
2665 if (builder_ == NULL) return; | 2486 if (builder_ == NULL || builder_->flow_graph_builder_ == NULL) return; |
2666 | 2487 |
2667 const Function& function = builder_->parsed_function()->function(); | 2488 const Function& function = builder_->parsed_function()->function(); |
2668 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { | 2489 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { |
2669 // Don't cache constants in initializer expressions. They get | 2490 // Don't cache constants in initializer expressions. They get |
2670 // evaluated only once. | 2491 // evaluated only once. |
2671 return; | 2492 return; |
2672 } | 2493 } |
2673 const intptr_t kInitialConstMapSize = 16; | 2494 const intptr_t kInitialConstMapSize = 16; |
2674 ASSERT(!script_.InVMHeap()); | 2495 ASSERT(!script_.InVMHeap()); |
2675 if (script_.compile_time_constants() == Array::null()) { | 2496 if (script_.compile_time_constants() == Array::null()) { |
2676 const Array& array = Array::Handle( | 2497 const Array& array = Array::Handle( |
2677 HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew)); | 2498 HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew)); |
2678 script_.set_compile_time_constants(array); | 2499 script_.set_compile_time_constants(array); |
2679 } | 2500 } |
2680 KernelConstantsMap constants(script_.compile_time_constants()); | 2501 KernelConstantsMap constants(script_.compile_time_constants()); |
2681 constants.InsertNewOrGetValue(kernel_offset, value); | 2502 constants.InsertNewOrGetValue(kernel_offset, value); |
2682 script_.set_compile_time_constants(constants.Release()); | 2503 script_.set_compile_time_constants(constants.Release()); |
2683 } | 2504 } |
2684 | 2505 |
2685 | 2506 void StreamingFlowGraphBuilder::DiscoverEnclosingElements( |
2686 Fragment StreamingFlowGraphBuilder::BuildExpressionAt(intptr_t kernel_offset) { | 2507 Zone* zone, |
| 2508 const Function& function, |
| 2509 Function* outermost_function, |
| 2510 intptr_t* outermost_kernel_offset, |
| 2511 intptr_t* parent_class_offset) { |
| 2512 // Find out if there is an enclosing kernel class (which will be used to |
| 2513 // resolve type parameters). |
| 2514 *outermost_function = function.raw(); |
| 2515 while (outermost_function->parent_function() != Object::null()) { |
| 2516 *outermost_function = outermost_function->parent_function(); |
| 2517 } |
| 2518 |
| 2519 if (outermost_function->kernel_offset() > 0) { |
| 2520 *outermost_kernel_offset = outermost_function->kernel_offset(); |
| 2521 *parent_class_offset = GetParentOffset(*outermost_kernel_offset); |
| 2522 } |
| 2523 } |
| 2524 |
| 2525 intptr_t StreamingFlowGraphBuilder::GetParentOffset(intptr_t offset) { |
| 2526 AlternativeReadingScope alt(reader_, offset); |
| 2527 |
| 2528 Tag tag = PeekTag(); |
| 2529 intptr_t parent_offset = -1; |
| 2530 switch (tag) { |
| 2531 case kConstructor: |
| 2532 return ReadConstructorUntilFunctionNode(); |
| 2533 case kProcedure: |
| 2534 ReadProcedureUntilFunctionNode( |
| 2535 &unused_word, &parent_offset); // read first part of procedure. |
| 2536 return parent_offset; |
| 2537 case kField: |
| 2538 ReadFieldUntilAnnotation(&unused_nameindex, &unused_tokenposition, |
| 2539 &unused_tokenposition, &unused_word, |
| 2540 &parent_offset); |
| 2541 return parent_offset; |
| 2542 default: |
| 2543 UNIMPLEMENTED(); |
| 2544 return -1; |
| 2545 } |
| 2546 } |
| 2547 |
| 2548 void StreamingFlowGraphBuilder::GetTypeParameterInfoForClass( |
| 2549 intptr_t class_offset, |
| 2550 intptr_t* type_paremeter_counts, |
| 2551 intptr_t* type_paremeter_offset) { |
| 2552 AlternativeReadingScope alt(reader_, class_offset); |
| 2553 |
| 2554 ReadClassUntilTypeParameters(); |
| 2555 *type_paremeter_counts = |
| 2556 ReadListLength(); // read type_parameters list length. |
| 2557 *type_paremeter_offset = ReaderOffset(); |
| 2558 } |
| 2559 |
| 2560 void StreamingFlowGraphBuilder::ReadClassUntilFields() { |
| 2561 ReadClassUntilTypeParameters(); |
| 2562 SkipTypeParametersList(); // read type_parameters. |
| 2563 Tag type_tag = ReadTag(); // read type (part 1). |
| 2564 if (type_tag == kSomething) { |
| 2565 SkipDartType(); // read type (part 2). |
| 2566 } |
| 2567 type_tag = ReadTag(); // read Mixed-in type (part 1). |
| 2568 if (type_tag == kSomething) { |
| 2569 SkipDartType(); // read Mixed-in type (part 2). |
| 2570 } |
| 2571 SkipListOfDartTypes(); // read implemented_classes. |
| 2572 } |
| 2573 |
| 2574 void StreamingFlowGraphBuilder::ReadClassUntilTypeParameters() { |
| 2575 Tag class_tag = ReadTag(); |
| 2576 ASSERT(class_tag == kClass); |
| 2577 SkipCanonicalNameReference(); // read canonical_name. |
| 2578 ReadPosition(); // read position. |
| 2579 ReadBool(); // read is_abstract. |
| 2580 SkipStringReference(); // read name index. |
| 2581 ReadUInt(); // read source_uri_index. |
| 2582 SkipListOfExpressions(); // read annotations. |
| 2583 } |
| 2584 |
| 2585 intptr_t StreamingFlowGraphBuilder::ReadConstructorUntilFunctionNode() { |
| 2586 Tag tag = ReadTag(); |
| 2587 ASSERT(tag == kConstructor); |
| 2588 SkipCanonicalNameReference(); // read canonical name reference. |
| 2589 ReadPosition(); // read position. |
| 2590 ReadPosition(); // read end position. |
| 2591 ReadFlags(); // read flags. |
| 2592 intptr_t parent_offset = ReadUInt(); // parent class binary offset. |
| 2593 SkipName(); // read name. |
| 2594 SkipListOfExpressions(); // read annotations. |
| 2595 return parent_offset; |
| 2596 } |
| 2597 |
| 2598 Tag StreamingFlowGraphBuilder::ReadProcedureUntilFunctionNode( |
| 2599 word* kind, |
| 2600 intptr_t* parent_offset) { |
| 2601 Tag tag = ReadTag(); // read tag. |
| 2602 ASSERT(tag == kProcedure); |
| 2603 SkipCanonicalNameReference(); // read canonical name reference. |
| 2604 ReadPosition(); // read position. |
| 2605 ReadPosition(); // read end position. |
| 2606 *kind = ReadByte(); // read kind. |
| 2607 ReadFlags(); // read flags. |
| 2608 *parent_offset = ReadUInt(); // read parent class binary offset. |
| 2609 SkipName(); // read name, |
| 2610 ReadUInt(); // read source_uri_index. |
| 2611 SkipListOfExpressions(); // read annotations. |
| 2612 return ReadTag(); // read tag for optional function node. |
| 2613 } |
| 2614 |
| 2615 void StreamingFlowGraphBuilder::ReadFieldUntilAnnotation( |
| 2616 NameIndex* canonical_name, |
| 2617 TokenPosition* position, |
| 2618 TokenPosition* end_position, |
| 2619 word* flags, |
| 2620 intptr_t* parent_offset) { |
| 2621 Tag tag = ReadTag(); |
| 2622 ASSERT(tag == kField); |
| 2623 |
| 2624 *canonical_name = ReadCanonicalNameReference(); // read canonical_name. |
| 2625 *position = ReadPosition(); // read position. |
| 2626 *end_position = ReadPosition(); // read end position. |
| 2627 *flags = ReadFlags(); // read flags. |
| 2628 *parent_offset = ReadUInt(); // read parent class binary offset. |
| 2629 SkipName(); // read name. |
| 2630 ReadUInt(); // source_uri_index. |
| 2631 } |
| 2632 |
| 2633 void StreamingFlowGraphBuilder::GetTypeParameterInfoForPossibleProcedure( |
| 2634 intptr_t outermost_kernel_offset, |
| 2635 bool* member_is_procedure, |
| 2636 bool* is_factory_procedure, |
| 2637 intptr_t* member_type_parameters, |
| 2638 intptr_t* member_type_parameters_offset_start) { |
| 2639 if (outermost_kernel_offset >= 0) { |
| 2640 AlternativeReadingScope alt(reader_, outermost_kernel_offset); |
| 2641 Tag tag = PeekTag(); |
| 2642 if (tag == kProcedure) { |
| 2643 *member_is_procedure = true; |
| 2644 |
| 2645 word kind; |
| 2646 tag = ReadProcedureUntilFunctionNode( |
| 2647 &kind, &unused_intptr); // read first part of procedure. |
| 2648 *is_factory_procedure = |
| 2649 static_cast<Procedure::ProcedureKind>(kind) == Procedure::kFactory; |
| 2650 |
| 2651 if (tag == kSomething) { |
| 2652 ReadFunctionNodeUntilTypeParameters( |
| 2653 &unused_tokenposition, &unused_tokenposition, &unused_word, |
| 2654 &unused_word); // read first part of function node. |
| 2655 |
| 2656 intptr_t list_length = |
| 2657 ReadListLength(); // read type_parameters list length. |
| 2658 if (list_length > 0) { |
| 2659 *member_type_parameters = list_length; |
| 2660 *member_type_parameters_offset_start = ReaderOffset(); |
| 2661 } |
| 2662 } |
| 2663 } |
| 2664 } |
| 2665 } |
| 2666 |
| 2667 void StreamingFlowGraphBuilder::ReadFunctionNodeUntilTypeParameters( |
| 2668 TokenPosition* position, |
| 2669 TokenPosition* end_position, |
| 2670 word* async_marker, |
| 2671 word* dart_async_marker) { |
| 2672 Tag tag = ReadTag(); // read tag. |
| 2673 ASSERT(tag == kFunctionNode); |
| 2674 |
| 2675 *position = ReadPosition(); // read position. |
| 2676 *end_position = ReadPosition(); // read end position. |
| 2677 *async_marker = ReadByte(); // read async marker. |
| 2678 *dart_async_marker = ReadByte(); // read dart async marker. |
| 2679 } |
| 2680 |
| 2681 intptr_t StreamingFlowGraphBuilder::ReadUntilFunctionNode() { |
| 2682 const Tag tag = PeekTag(); |
| 2683 if (tag == kProcedure) { |
| 2684 Tag has_function_node = ReadProcedureUntilFunctionNode( |
| 2685 &unused_word, &unused_intptr); // read first part of procedure. |
| 2686 if (has_function_node == kNothing) { |
| 2687 // Running a procedure without a function node doesn't make sense. |
| 2688 UNREACHABLE(); |
| 2689 } |
| 2690 return -1; |
| 2691 // Now at start of FunctionNode. |
| 2692 } else if (tag == kConstructor) { |
| 2693 // read first part of constructor. |
| 2694 return ReadConstructorUntilFunctionNode(); |
| 2695 // Now at start of FunctionNode. |
| 2696 // Notice that we also have a list of initializers after that! |
| 2697 } else if (tag == kFunctionNode) { |
| 2698 // Already at start of FunctionNode. |
| 2699 } else { |
| 2700 UNREACHABLE(); |
| 2701 } |
| 2702 return -1; |
| 2703 } |
| 2704 |
| 2705 StringIndex StreamingFlowGraphBuilder::GetNameFromVariableDeclaration( |
| 2706 intptr_t kernel_offset) { |
| 2707 // Temporarily go to the variable declaration, read the name. |
| 2708 AlternativeReadingScope alt(reader_, kernel_offset); |
| 2709 ReadPosition(); // read position. |
| 2710 ReadPosition(); // read equals position. |
| 2711 ReadFlags(); // read flags. |
| 2712 return ReadStringReference(); // read name index. |
| 2713 } |
| 2714 |
| 2715 FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfStaticFieldInitializer() { |
| 2716 TokenPosition position; |
| 2717 TokenPosition end_position; |
| 2718 word flags; |
| 2719 ReadFieldUntilAnnotation(&unused_nameindex, &position, &end_position, &flags, |
| 2720 &unused_intptr); |
| 2721 bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic; |
| 2722 bool is_const = (flags & Field::kFlagConst) == Field::kFlagConst; |
| 2723 ASSERT(is_static); |
| 2724 |
| 2725 SkipListOfExpressions(); // read annotations. |
| 2726 SkipDartType(); // read type. |
| 2727 Tag initializer_tag = ReadTag(); // read first part of initializer. |
| 2728 if (initializer_tag != kSomething) { |
| 2729 UNREACHABLE(); |
| 2730 } |
| 2731 |
| 2732 TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry(); |
| 2733 flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr( |
| 2734 *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId); |
| 2735 |
| 2736 Fragment body(normal_entry); |
| 2737 body += flow_graph_builder_->CheckStackOverflowInPrologue(); |
| 2738 if (is_const) { |
| 2739 // this will (potentially) read the initializer, but reset the position. |
| 2740 body += Constant(constant_evaluator_.EvaluateExpression(ReaderOffset())); |
| 2741 SkipExpression(); // read the initializer. |
| 2742 } else { |
| 2743 body += BuildExpression(); // read initializer. |
| 2744 } |
| 2745 body += Return(TokenPosition::kNoSource); |
| 2746 |
| 2747 return new (Z) |
| 2748 FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_, |
| 2749 flow_graph_builder_->next_block_id_ - 1); |
| 2750 } |
| 2751 |
| 2752 FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldAccessor( |
| 2753 LocalVariable* setter_value) { |
| 2754 NameIndex canonical_name; |
| 2755 ReadFieldUntilAnnotation(&canonical_name, &unused_tokenposition, |
| 2756 &unused_tokenposition, &unused_word, &unused_intptr); |
| 2757 SkipListOfExpressions(); // read annotations. |
| 2758 SkipDartType(); // read type. |
| 2759 Tag initializer_tag = ReadTag(); // read first part of initializer. |
| 2760 |
| 2761 const Function& function = parsed_function()->function(); |
| 2762 |
| 2763 bool is_setter = function.IsImplicitSetterFunction(); |
| 2764 bool is_method = !function.IsStaticFunction(); |
| 2765 dart::Field& field = |
| 2766 dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(canonical_name)); |
| 2767 |
| 2768 TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry(); |
| 2769 flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr( |
| 2770 *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId); |
| 2771 |
| 2772 Fragment body(normal_entry); |
| 2773 if (is_setter) { |
| 2774 if (is_method) { |
| 2775 body += LoadLocal(scopes()->this_variable); |
| 2776 body += LoadLocal(setter_value); |
| 2777 body += flow_graph_builder_->StoreInstanceFieldGuarded(field, false); |
| 2778 } else { |
| 2779 body += LoadLocal(setter_value); |
| 2780 body += StoreStaticField(TokenPosition::kNoSource, field); |
| 2781 } |
| 2782 body += NullConstant(); |
| 2783 } else if (is_method) { |
| 2784 body += LoadLocal(scopes()->this_variable); |
| 2785 body += flow_graph_builder_->LoadField(field); |
| 2786 } else if (field.is_const()) { |
| 2787 // If the parser needs to know the value of an uninitialized constant field |
| 2788 // it will set the value to the transition sentinel (used to detect circular |
| 2789 // initialization) and then call the implicit getter. Thus, the getter |
| 2790 // cannot contain the InitStaticField instruction that normal static getters |
| 2791 // contain because it would detect spurious circular initialization when it |
| 2792 // checks for the transition sentinel. |
| 2793 ASSERT(initializer_tag == kSomething); |
| 2794 // this will (potentially) read the initializer, but reset the position. |
| 2795 body += Constant(constant_evaluator_.EvaluateExpression(ReaderOffset())); |
| 2796 SkipExpression(); // read the initializer. |
| 2797 } else { |
| 2798 // The field always has an initializer because static fields without |
| 2799 // initializers are initialized eagerly and do not have implicit getters. |
| 2800 ASSERT(field.has_initializer()); |
| 2801 body += Constant(field); |
| 2802 body += flow_graph_builder_->InitStaticField(field); |
| 2803 body += Constant(field); |
| 2804 body += LoadStaticField(); |
| 2805 } |
| 2806 body += Return(TokenPosition::kNoSource); |
| 2807 |
| 2808 return new (Z) |
| 2809 FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_, |
| 2810 flow_graph_builder_->next_block_id_ - 1); |
| 2811 } |
| 2812 |
| 2813 void StreamingFlowGraphBuilder::SetupDefaultParameterValues() { |
| 2814 intptr_t num_optional_parameters = |
| 2815 parsed_function()->function().NumOptionalParameters(); |
| 2816 if (num_optional_parameters > 0) { |
| 2817 ZoneGrowableArray<const Instance*>* default_values = |
| 2818 new ZoneGrowableArray<const Instance*>(Z, num_optional_parameters); |
| 2819 |
| 2820 AlternativeReadingScope alt(reader_); |
| 2821 ReadFunctionNodeUntilTypeParameters( |
| 2822 &unused_tokenposition, &unused_tokenposition, &unused_word, |
| 2823 &unused_word); // read first part of function node. |
| 2824 SkipTypeParametersList(); // read type_parameters. |
| 2825 intptr_t required = ReadUInt(); // read required_parameter_count. |
| 2826 ReadUInt(); // read total parameter count. |
| 2827 |
| 2828 if (parsed_function()->function().HasOptionalNamedParameters()) { |
| 2829 // List of positional. |
| 2830 intptr_t list_length = ReadListLength(); // read list length. |
| 2831 for (intptr_t i = 0; i < list_length; ++i) { |
| 2832 SkipVariableDeclaration(); // read ith variable declaration. |
| 2833 } |
| 2834 |
| 2835 // List of named. |
| 2836 list_length = ReadListLength(); // read list length. |
| 2837 ASSERT(num_optional_parameters == list_length); |
| 2838 ASSERT(!parsed_function()->function().HasOptionalPositionalParameters()); |
| 2839 for (intptr_t i = 0; i < list_length; ++i) { |
| 2840 Instance* default_value; |
| 2841 |
| 2842 // Read ith variable declaration |
| 2843 ReadPosition(); // read position. |
| 2844 ReadPosition(); // read equals position. |
| 2845 ReadFlags(); // read flags. |
| 2846 SkipStringReference(); // read name index. |
| 2847 SkipDartType(); // read type. |
| 2848 Tag tag = ReadTag(); // read (first part of) initializer. |
| 2849 if (tag == kSomething) { |
| 2850 // this will (potentially) read the initializer, |
| 2851 // but reset the position. |
| 2852 default_value = |
| 2853 &constant_evaluator_.EvaluateExpression(ReaderOffset()); |
| 2854 SkipExpression(); // read (actual) initializer. |
| 2855 } else { |
| 2856 default_value = &Instance::ZoneHandle(Z, Instance::null()); |
| 2857 } |
| 2858 default_values->Add(default_value); |
| 2859 } |
| 2860 } else { |
| 2861 // List of positional. |
| 2862 intptr_t list_length = ReadListLength(); // read list length. |
| 2863 ASSERT(list_length == required + num_optional_parameters); |
| 2864 ASSERT(parsed_function()->function().HasOptionalPositionalParameters()); |
| 2865 for (intptr_t i = 0; i < required; ++i) { |
| 2866 SkipVariableDeclaration(); // read ith variable declaration. |
| 2867 } |
| 2868 for (intptr_t i = 0; i < num_optional_parameters; ++i) { |
| 2869 Instance* default_value; |
| 2870 |
| 2871 // Read ith variable declaration |
| 2872 ReadPosition(); // read position. |
| 2873 ReadPosition(); // read equals position. |
| 2874 ReadFlags(); // read flags. |
| 2875 SkipStringReference(); // read name index. |
| 2876 SkipDartType(); // read type. |
| 2877 Tag tag = ReadTag(); // read (first part of) initializer. |
| 2878 if (tag == kSomething) { |
| 2879 // this will (potentially) read the initializer, |
| 2880 // but reset the position. |
| 2881 default_value = |
| 2882 &constant_evaluator_.EvaluateExpression(ReaderOffset()); |
| 2883 SkipExpression(); // read (actual) initializer. |
| 2884 } else { |
| 2885 default_value = &Instance::ZoneHandle(Z, Instance::null()); |
| 2886 } |
| 2887 default_values->Add(default_value); |
| 2888 } |
| 2889 |
| 2890 // List of named. |
| 2891 list_length = ReadListLength(); // read list length. |
| 2892 ASSERT(list_length == 0); |
| 2893 } |
| 2894 parsed_function()->set_default_parameter_values(default_values); |
| 2895 } |
| 2896 } |
| 2897 |
| 2898 Fragment StreamingFlowGraphBuilder::BuildFieldInitializer( |
| 2899 NameIndex canonical_name) { |
| 2900 dart::Field& field = |
| 2901 dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(canonical_name)); |
| 2902 if (PeekTag() == kNullLiteral) { |
| 2903 SkipExpression(); // read past the null literal. |
| 2904 field.RecordStore(Object::null_object()); |
| 2905 return Fragment(); |
| 2906 } |
| 2907 |
| 2908 Fragment instructions; |
| 2909 instructions += LoadLocal(scopes()->this_variable); |
| 2910 instructions += BuildExpression(); |
| 2911 instructions += flow_graph_builder_->StoreInstanceFieldGuarded(field, true); |
| 2912 return instructions; |
| 2913 } |
| 2914 |
| 2915 Fragment StreamingFlowGraphBuilder::BuildInitializers( |
| 2916 intptr_t constructor_class_parent_offset) { |
| 2917 Fragment instructions; |
| 2918 |
| 2919 // These come from: |
| 2920 // class A { |
| 2921 // var x = (expr); |
| 2922 // } |
| 2923 { |
| 2924 AlternativeReadingScope alt(reader_, constructor_class_parent_offset); |
| 2925 ReadClassUntilFields(); // read first part of class. |
| 2926 intptr_t list_length = ReadListLength(); // read fields list length. |
| 2927 |
| 2928 for (intptr_t i = 0; i < list_length; ++i) { |
| 2929 intptr_t field_offset = ReaderOffset(); |
| 2930 NameIndex canonical_name; |
| 2931 TokenPosition position; |
| 2932 TokenPosition end_position; |
| 2933 word flags; |
| 2934 ReadFieldUntilAnnotation(&canonical_name, &position, &end_position, |
| 2935 &flags, &unused_intptr); |
| 2936 bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic; |
| 2937 SkipListOfExpressions(); // read annotations. |
| 2938 SkipDartType(); // read type. |
| 2939 Tag initializer_tag = ReadTag(); // read first part of initializer. |
| 2940 if (!is_static && initializer_tag == kSomething) { |
| 2941 EnterScope(field_offset); |
| 2942 instructions += |
| 2943 BuildFieldInitializer(canonical_name); // read initializer. |
| 2944 ExitScope(field_offset); |
| 2945 } else if (initializer_tag == kSomething) { |
| 2946 SkipExpression(); // read initializer. |
| 2947 } |
| 2948 } |
| 2949 } |
| 2950 |
| 2951 // These to come from: |
| 2952 // class A { |
| 2953 // var x; |
| 2954 // var y; |
| 2955 // A(this.x) : super(expr), y = (expr); |
| 2956 // } |
| 2957 { |
| 2958 AlternativeReadingScope alt(reader_); |
| 2959 SkipFunctionNode(); // read constructors function node. |
| 2960 |
| 2961 intptr_t list_length = ReadListLength(); // read initializers list length. |
| 2962 for (intptr_t i = 0; i < list_length; ++i) { |
| 2963 Tag tag = ReadTag(); |
| 2964 switch (tag) { |
| 2965 case kInvalidInitializer: |
| 2966 UNIMPLEMENTED(); |
| 2967 return Fragment(); |
| 2968 case kFieldInitializer: { |
| 2969 NameIndex canonical_name = |
| 2970 ReadCanonicalNameReference(); // read field_reference. |
| 2971 instructions += BuildFieldInitializer(canonical_name); // read value. |
| 2972 break; |
| 2973 } |
| 2974 case kSuperInitializer: { |
| 2975 NameIndex canonical_target = |
| 2976 ReadCanonicalNameReference(); // read target_reference. |
| 2977 |
| 2978 instructions += LoadLocal(scopes()->this_variable); |
| 2979 instructions += PushArgument(); |
| 2980 |
| 2981 // TODO(jensj): ASSERT(init->arguments()->types().length() == 0); |
| 2982 Array& argument_names = Array::ZoneHandle(Z); |
| 2983 intptr_t argument_count; |
| 2984 instructions += BuildArguments(&argument_names, |
| 2985 &argument_count); // read arguments. |
| 2986 argument_count += 1; |
| 2987 |
| 2988 const Function& target = Function::ZoneHandle( |
| 2989 Z, H.LookupConstructorByKernelConstructor(canonical_target)); |
| 2990 instructions += StaticCall(TokenPosition::kNoSource, target, |
| 2991 argument_count, argument_names); |
| 2992 instructions += Drop(); |
| 2993 break; |
| 2994 } |
| 2995 case kRedirectingInitializer: { |
| 2996 NameIndex canonical_target = |
| 2997 ReadCanonicalNameReference(); // read target_reference. |
| 2998 |
| 2999 instructions += LoadLocal(scopes()->this_variable); |
| 3000 instructions += PushArgument(); |
| 3001 |
| 3002 // TODO(jensj): ASSERT(init->arguments()->types().length() == 0); |
| 3003 Array& argument_names = Array::ZoneHandle(Z); |
| 3004 intptr_t argument_count; |
| 3005 instructions += BuildArguments(&argument_names, |
| 3006 &argument_count); // read arguments. |
| 3007 argument_count += 1; |
| 3008 |
| 3009 const Function& target = Function::ZoneHandle( |
| 3010 Z, H.LookupConstructorByKernelConstructor(canonical_target)); |
| 3011 instructions += StaticCall(TokenPosition::kNoSource, target, |
| 3012 argument_count, argument_names); |
| 3013 instructions += Drop(); |
| 3014 break; |
| 3015 } |
| 3016 case kLocalInitializer: { |
| 3017 // The other initializers following this one might read the variable. |
| 3018 // This is used e.g. for evaluating the arguments to a super call |
| 3019 // first, run normal field initializers next and then make the actual |
| 3020 // super call: |
| 3021 // |
| 3022 // The frontend converts |
| 3023 // |
| 3024 // class A { |
| 3025 // var x; |
| 3026 // A(a, b) : super(a + b), x = 2*b {} |
| 3027 // } |
| 3028 // |
| 3029 // to |
| 3030 // |
| 3031 // class A { |
| 3032 // var x; |
| 3033 // A(a, b) : tmp = a + b, x = 2*b, super(tmp) {} |
| 3034 // } |
| 3035 // |
| 3036 // (This is strictly speaking not what one should do in terms of the |
| 3037 // specification but that is how it is currently implemented.) |
| 3038 LocalVariable* variable = LookupVariable(ReaderOffset()); |
| 3039 |
| 3040 // Variable declaration |
| 3041 ReadPosition(); // read position. |
| 3042 ReadPosition(); // read equals position. |
| 3043 word flags = ReadFlags(); // read flags. |
| 3044 ASSERT((flags & VariableDeclaration::kFlagConst) != |
| 3045 VariableDeclaration::kFlagConst); |
| 3046 SkipStringReference(); // read name index. |
| 3047 SkipDartType(); // read type. |
| 3048 Tag tag = ReadTag(); // read (first part of) initializer. |
| 3049 if (tag != kSomething) { |
| 3050 UNREACHABLE(); |
| 3051 } |
| 3052 |
| 3053 instructions += BuildExpression(); // read initializer. |
| 3054 instructions += StoreLocal(TokenPosition::kNoSource, variable); |
| 3055 instructions += Drop(); |
| 3056 break; |
| 3057 } |
| 3058 default: |
| 3059 UNREACHABLE(); |
| 3060 } |
| 3061 } |
| 3062 } |
| 3063 return instructions; |
| 3064 } |
| 3065 |
| 3066 FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfImplicitClosureFunction( |
| 3067 const Function& function) { |
| 3068 const Function& target = Function::ZoneHandle(Z, function.parent_function()); |
| 3069 |
| 3070 TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry(); |
| 3071 flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr( |
| 3072 *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId); |
| 3073 SetupDefaultParameterValues(); |
| 3074 |
| 3075 Fragment body(normal_entry); |
| 3076 body += flow_graph_builder_->CheckStackOverflowInPrologue(); |
| 3077 |
| 3078 // Load all the arguments. |
| 3079 if (!target.is_static()) { |
| 3080 // The context has a fixed shape: a single variable which is the |
| 3081 // closed-over receiver. |
| 3082 body += LoadLocal(parsed_function()->current_context_var()); |
| 3083 body += flow_graph_builder_->LoadField(Context::variable_offset(0)); |
| 3084 body += PushArgument(); |
| 3085 } |
| 3086 |
| 3087 TokenPosition end_position; |
| 3088 ReadFunctionNodeUntilTypeParameters( |
| 3089 &unused_tokenposition, &end_position, &unused_word, |
| 3090 &unused_word); // read first part of function node. |
| 3091 SkipTypeParametersList(); // read type parameter list. |
| 3092 ReadUInt(); // read required_parameter_count. |
| 3093 ReadUInt(); // read total parameter count. |
| 3094 |
| 3095 // Positional. |
| 3096 intptr_t positional_argument_count = ReadListLength(); |
| 3097 for (intptr_t i = 0; i < positional_argument_count; ++i) { |
| 3098 body += LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset. |
| 3099 body += PushArgument(); |
| 3100 SkipVariableDeclaration(); // read ith variable. |
| 3101 } |
| 3102 |
| 3103 // Named. |
| 3104 intptr_t named_argument_count = ReadListLength(); |
| 3105 Array& argument_names = Array::ZoneHandle(Z); |
| 3106 if (named_argument_count > 0) { |
| 3107 argument_names = Array::New(named_argument_count); |
| 3108 for (intptr_t i = 0; i < named_argument_count; ++i) { |
| 3109 body += |
| 3110 LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset. |
| 3111 body += PushArgument(); |
| 3112 argument_names.SetAt( |
| 3113 i, H.DartSymbol(GetNameFromVariableDeclaration(ReaderOffset()))); |
| 3114 SkipVariableDeclaration(); // read ith variable. |
| 3115 } |
| 3116 } |
| 3117 |
| 3118 // Forward them to the target. |
| 3119 intptr_t argument_count = positional_argument_count + named_argument_count; |
| 3120 if (!target.is_static()) ++argument_count; |
| 3121 body += StaticCall(TokenPosition::kNoSource, target, argument_count, |
| 3122 argument_names); |
| 3123 |
| 3124 // Return the result. |
| 3125 body += Return(end_position); |
| 3126 |
| 3127 return new (Z) |
| 3128 FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_, |
| 3129 flow_graph_builder_->next_block_id_ - 1); |
| 3130 } |
| 3131 |
| 3132 static bool IsGetMainClosure(const String& name) { |
| 3133 if (name.Length() < 16) return false; |
| 3134 const char* cstr = "_getMainClosure@"; |
| 3135 for (intptr_t i = 0; i < 16; ++i) { |
| 3136 if (name.CharAt(i) != cstr[i]) return false; |
| 3137 } |
| 3138 return true; |
| 3139 } |
| 3140 |
| 3141 FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFunction( |
| 3142 bool is_in_builtin_library_toplevel, |
| 3143 intptr_t constructor_class_parent_offset) { |
| 3144 const Function& dart_function = parsed_function()->function(); |
| 3145 TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry(); |
| 3146 flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr( |
| 3147 *parsed_function(), normal_entry, flow_graph_builder_->osr_id_); |
| 3148 |
| 3149 SetupDefaultParameterValues(); |
| 3150 |
| 3151 Fragment body; |
| 3152 if (!dart_function.is_native()) |
| 3153 body += flow_graph_builder_->CheckStackOverflowInPrologue(); |
| 3154 intptr_t context_size = |
| 3155 parsed_function()->node_sequence()->scope()->num_context_variables(); |
| 3156 if (context_size > 0) { |
| 3157 body += flow_graph_builder_->PushContext(context_size); |
| 3158 LocalVariable* context = MakeTemporary(); |
| 3159 |
| 3160 // Copy captured parameters from the stack into the context. |
| 3161 LocalScope* scope = parsed_function()->node_sequence()->scope(); |
| 3162 intptr_t parameter_count = dart_function.NumParameters(); |
| 3163 intptr_t parameter_index = parsed_function()->first_parameter_index(); |
| 3164 for (intptr_t i = 0; i < parameter_count; ++i, --parameter_index) { |
| 3165 LocalVariable* variable = scope->VariableAt(i); |
| 3166 if (variable->is_captured()) { |
| 3167 // There is no LocalVariable describing the on-stack parameter so |
| 3168 // create one directly and use the same type. |
| 3169 LocalVariable* parameter = new (Z) |
| 3170 LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
| 3171 Symbols::TempParam(), variable->type()); |
| 3172 parameter->set_index(parameter_index); |
| 3173 // Mark the stack variable so it will be ignored by the code for |
| 3174 // try/catch. |
| 3175 parameter->set_is_captured_parameter(true); |
| 3176 |
| 3177 // Copy the parameter from the stack to the context. Overwrite it |
| 3178 // with a null constant on the stack so the original value is |
| 3179 // eligible for garbage collection. |
| 3180 body += LoadLocal(context); |
| 3181 body += LoadLocal(parameter); |
| 3182 body += flow_graph_builder_->StoreInstanceField( |
| 3183 TokenPosition::kNoSource, |
| 3184 Context::variable_offset(variable->index())); |
| 3185 body += NullConstant(); |
| 3186 body += StoreLocal(TokenPosition::kNoSource, parameter); |
| 3187 body += Drop(); |
| 3188 } |
| 3189 } |
| 3190 body += Drop(); // The context. |
| 3191 } |
| 3192 if (constructor_class_parent_offset > 0) { |
| 3193 // TODO(27590): Currently the [VariableDeclaration]s from the |
| 3194 // initializers will be visible inside the entire body of the constructor. |
| 3195 // We should make a separate scope for them. |
| 3196 body += BuildInitializers(constructor_class_parent_offset); |
| 3197 } |
| 3198 |
| 3199 TokenPosition position; |
| 3200 ReadFunctionNodeUntilTypeParameters( |
| 3201 &position, &unused_tokenposition, &unused_word, |
| 3202 &unused_word); // read first part of function node. |
| 3203 SkipTypeParametersList(); // read type parameter list. |
| 3204 ReadUInt(); // read required_parameter_count. |
| 3205 ReadUInt(); // read total parameter count |
| 3206 intptr_t first_parameter_offset = -1; |
| 3207 { |
| 3208 AlternativeReadingScope alt(reader_); |
| 3209 intptr_t list_length = ReadListLength(); // read number of positionals. |
| 3210 if (list_length > 0) { |
| 3211 first_parameter_offset = ReaderOffset(); |
| 3212 } |
| 3213 } |
| 3214 // Current position: About to read list of positionals. |
| 3215 |
| 3216 // The specification defines the result of `a == b` to be: |
| 3217 // |
| 3218 // a) if either side is `null` then the result is `identical(a, b)`. |
| 3219 // b) else the result is `a.operator==(b)` |
| 3220 // |
| 3221 // For user-defined implementations of `operator==` we need therefore |
| 3222 // implement the handling of a). |
| 3223 // |
| 3224 // The default `operator==` implementation in `Object` is implemented in terms |
| 3225 // of identical (which we assume here!) which means that case a) is actually |
| 3226 // included in b). So we just use the normal implementation in the body. |
| 3227 if ((dart_function.NumParameters() == 2) && |
| 3228 (dart_function.name() == Symbols::EqualOperator().raw()) && |
| 3229 (dart_function.Owner() != I->object_store()->object_class())) { |
| 3230 LocalVariable* parameter = LookupVariable(first_parameter_offset); |
| 3231 |
| 3232 TargetEntryInstr* null_entry; |
| 3233 TargetEntryInstr* non_null_entry; |
| 3234 |
| 3235 body += LoadLocal(parameter); |
| 3236 body += BranchIfNull(&null_entry, &non_null_entry); |
| 3237 |
| 3238 // The argument was `null` and the receiver is not the null class (we only |
| 3239 // go into this branch for user-defined == operators) so we can return |
| 3240 // false. |
| 3241 Fragment null_fragment(null_entry); |
| 3242 null_fragment += Constant(Bool::False()); |
| 3243 null_fragment += Return(dart_function.end_token_pos()); |
| 3244 |
| 3245 body = Fragment(body.entry, non_null_entry); |
| 3246 } |
| 3247 |
| 3248 // If we run in checked mode, we have to check the type of the passed |
| 3249 // arguments. |
| 3250 if (I->type_checks()) { |
| 3251 // Positional. |
| 3252 intptr_t list_length = ReadListLength(); |
| 3253 for (intptr_t i = 0; i < list_length; ++i) { |
| 3254 body += |
| 3255 LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset. |
| 3256 body += CheckVariableTypeInCheckedMode(ReaderOffset()); |
| 3257 body += Drop(); |
| 3258 SkipVariableDeclaration(); // read ith variable. |
| 3259 } |
| 3260 |
| 3261 // Named. |
| 3262 list_length = ReadListLength(); |
| 3263 for (intptr_t i = 0; i < list_length; ++i) { |
| 3264 body += |
| 3265 LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset. |
| 3266 body += CheckVariableTypeInCheckedMode(ReaderOffset()); |
| 3267 body += Drop(); |
| 3268 SkipVariableDeclaration(); // read ith variable. |
| 3269 } |
| 3270 } else { |
| 3271 // Still skip past the parameters. |
| 3272 SkipListOfVariableDeclarations(); // read list of positionals. |
| 3273 SkipListOfVariableDeclarations(); // read list of named. |
| 3274 } |
| 3275 |
| 3276 SkipDartType(); // read return type. |
| 3277 |
| 3278 if (FLAG_causal_async_stacks && |
| 3279 (dart_function.IsAsyncFunction() || dart_function.IsAsyncGenerator())) { |
| 3280 LocalScope* scope = parsed_function()->node_sequence()->scope(); |
| 3281 // :async_stack_trace = _asyncStackTraceHelper(:async_op); |
| 3282 const dart::Library& async_lib = |
| 3283 dart::Library::Handle(dart::Library::AsyncLibrary()); |
| 3284 const Function& target = Function::ZoneHandle( |
| 3285 Z, |
| 3286 async_lib.LookupFunctionAllowPrivate(Symbols::AsyncStackTraceHelper())); |
| 3287 ASSERT(!target.IsNull()); |
| 3288 |
| 3289 // TODO(johnmccutchan): Why does this have the null value? |
| 3290 LocalVariable* async_op = |
| 3291 scope->child()->LookupVariable(Symbols::AsyncOperation(), false); |
| 3292 ASSERT(async_op != NULL); |
| 3293 ASSERT(async_op->is_captured()); |
| 3294 body += LoadLocal(async_op); |
| 3295 body += PushArgument(); |
| 3296 body += StaticCall(TokenPosition::kNoSource, target, 1); |
| 3297 LocalVariable* async_stack_trace_var = |
| 3298 scope->LookupVariable(Symbols::AsyncStackTraceVar(), false); |
| 3299 ASSERT(async_stack_trace_var != NULL); |
| 3300 body += StoreLocal(TokenPosition::kNoSource, async_stack_trace_var); |
| 3301 body += Drop(); |
| 3302 } |
| 3303 |
| 3304 bool has_body = ReadTag() == kSomething; // read first part of body. |
| 3305 |
| 3306 if (dart_function.is_native()) { |
| 3307 body += flow_graph_builder_->NativeFunctionBody(first_parameter_offset, |
| 3308 dart_function); |
| 3309 } else if (has_body) { |
| 3310 if (is_in_builtin_library_toplevel && |
| 3311 IsGetMainClosure(dart::String::Handle(Z, dart_function.name()))) { |
| 3312 body += BuildGetMainClosure(); |
| 3313 } else { |
| 3314 body += BuildStatement(); // read body. |
| 3315 } |
| 3316 } |
| 3317 if (body.is_open()) { |
| 3318 body += NullConstant(); |
| 3319 body += Return(dart_function.end_token_pos()); |
| 3320 } |
| 3321 |
| 3322 // If functions body contains any yield points build switch statement that |
| 3323 // selects a continuation point based on the value of :await_jump_var. |
| 3324 if (!yield_continuations().is_empty()) { |
| 3325 // The code we are building will be executed right after we enter |
| 3326 // the function and before any nested contexts are allocated. |
| 3327 // Reset current context_depth_ to match this. |
| 3328 const intptr_t current_context_depth = flow_graph_builder_->context_depth_; |
| 3329 flow_graph_builder_->context_depth_ = |
| 3330 scopes()->yield_jump_variable->owner()->context_level(); |
| 3331 |
| 3332 // Prepend an entry corresponding to normal entry to the function. |
| 3333 yield_continuations().InsertAt( |
| 3334 0, YieldContinuation(new (Z) DropTempsInstr(0, NULL), |
| 3335 CatchClauseNode::kInvalidTryIndex)); |
| 3336 yield_continuations()[0].entry->LinkTo(body.entry); |
| 3337 |
| 3338 // Build a switch statement. |
| 3339 Fragment dispatch; |
| 3340 |
| 3341 // Load :await_jump_var into a temporary. |
| 3342 dispatch += LoadLocal(scopes()->yield_jump_variable); |
| 3343 dispatch += StoreLocal(TokenPosition::kNoSource, scopes()->switch_variable); |
| 3344 dispatch += Drop(); |
| 3345 |
| 3346 BlockEntryInstr* block = NULL; |
| 3347 for (intptr_t i = 0; i < yield_continuations().length(); i++) { |
| 3348 if (i == 1) { |
| 3349 // This is not a normal entry but a resumption. Restore |
| 3350 // :current_context_var from :await_ctx_var. |
| 3351 // Note: after this point context_depth_ does not match current context |
| 3352 // depth so we should not access any local variables anymore. |
| 3353 dispatch += LoadLocal(scopes()->yield_context_variable); |
| 3354 dispatch += StoreLocal(TokenPosition::kNoSource, |
| 3355 parsed_function()->current_context_var()); |
| 3356 dispatch += Drop(); |
| 3357 } |
| 3358 if (i == (yield_continuations().length() - 1)) { |
| 3359 // We reached the last possility, no need to build more ifs. |
| 3360 // Continue to the last continuation. |
| 3361 // Note: continuations start with nop DropTemps instruction |
| 3362 // which acts like an anchor, so we need to skip it. |
| 3363 block->set_try_index(yield_continuations()[i].try_index); |
| 3364 dispatch <<= yield_continuations()[i].entry->next(); |
| 3365 break; |
| 3366 } |
| 3367 |
| 3368 // Build comparison: |
| 3369 // |
| 3370 // if (:await_ctx_var == i) { |
| 3371 // -> yield_continuations()[i] |
| 3372 // } else ... |
| 3373 // |
| 3374 TargetEntryInstr* then; |
| 3375 TargetEntryInstr* otherwise; |
| 3376 dispatch += LoadLocal(scopes()->switch_variable); |
| 3377 dispatch += IntConstant(i); |
| 3378 dispatch += flow_graph_builder_->BranchIfStrictEqual(&then, &otherwise); |
| 3379 |
| 3380 // True branch is linked to appropriate continuation point. |
| 3381 // Note: continuations start with nop DropTemps instruction |
| 3382 // which acts like an anchor, so we need to skip it. |
| 3383 then->LinkTo(yield_continuations()[i].entry->next()); |
| 3384 then->set_try_index(yield_continuations()[i].try_index); |
| 3385 // False branch will contain the next comparison. |
| 3386 dispatch = Fragment(dispatch.entry, otherwise); |
| 3387 block = otherwise; |
| 3388 } |
| 3389 body = dispatch; |
| 3390 |
| 3391 flow_graph_builder_->context_depth_ = current_context_depth; |
| 3392 } |
| 3393 |
| 3394 if (FLAG_causal_async_stacks && |
| 3395 (dart_function.IsAsyncClosure() || dart_function.IsAsyncGenClosure())) { |
| 3396 // The code we are building will be executed right after we enter |
| 3397 // the function and before any nested contexts are allocated. |
| 3398 // Reset current context_depth_ to match this. |
| 3399 const intptr_t current_context_depth = flow_graph_builder_->context_depth_; |
| 3400 flow_graph_builder_->context_depth_ = |
| 3401 scopes()->yield_jump_variable->owner()->context_level(); |
| 3402 |
| 3403 Fragment instructions; |
| 3404 LocalScope* scope = parsed_function()->node_sequence()->scope(); |
| 3405 |
| 3406 const Function& target = Function::ZoneHandle( |
| 3407 Z, I->object_store()->async_set_thread_stack_trace()); |
| 3408 ASSERT(!target.IsNull()); |
| 3409 |
| 3410 // Fetch and load :async_stack_trace |
| 3411 LocalVariable* async_stack_trace_var = |
| 3412 scope->LookupVariable(Symbols::AsyncStackTraceVar(), false); |
| 3413 ASSERT((async_stack_trace_var != NULL) && |
| 3414 async_stack_trace_var->is_captured()); |
| 3415 instructions += LoadLocal(async_stack_trace_var); |
| 3416 instructions += PushArgument(); |
| 3417 |
| 3418 // Call _asyncSetThreadStackTrace |
| 3419 instructions += StaticCall(TokenPosition::kNoSource, target, 1); |
| 3420 instructions += Drop(); |
| 3421 |
| 3422 body = instructions + body; |
| 3423 flow_graph_builder_->context_depth_ = current_context_depth; |
| 3424 } |
| 3425 |
| 3426 if (NeedsDebugStepCheck(dart_function, position)) { |
| 3427 // If a switch was added above: Start the switch by injecting a debuggable |
| 3428 // safepoint so stepping over an await works. |
| 3429 // If not, still start the body with a debuggable safepoint to ensure |
| 3430 // breaking on a method always happens, even if there are no |
| 3431 // assignments/calls/runtimecalls in the first basic block. |
| 3432 // Place this check at the last parameter to ensure parameters |
| 3433 // are in scope in the debugger at method entry. |
| 3434 const int num_params = dart_function.NumParameters(); |
| 3435 TokenPosition check_pos = TokenPosition::kNoSource; |
| 3436 if (num_params > 0) { |
| 3437 LocalScope* scope = parsed_function()->node_sequence()->scope(); |
| 3438 const LocalVariable& parameter = *scope->VariableAt(num_params - 1); |
| 3439 check_pos = parameter.token_pos(); |
| 3440 } |
| 3441 if (!check_pos.IsDebugPause()) { |
| 3442 // No parameters or synthetic parameters. |
| 3443 check_pos = position; |
| 3444 ASSERT(check_pos.IsDebugPause()); |
| 3445 } |
| 3446 body = DebugStepCheck(check_pos) + body; |
| 3447 } |
| 3448 |
| 3449 normal_entry->LinkTo(body.entry); |
| 3450 |
| 3451 // When compiling for OSR, use a depth first search to prune instructions |
| 3452 // unreachable from the OSR entry. Catch entries are always considered |
| 3453 // reachable, even if they become unreachable after OSR. |
| 3454 if (flow_graph_builder_->osr_id_ != Compiler::kNoOSRDeoptId) { |
| 3455 BitVector* block_marks = |
| 3456 new (Z) BitVector(Z, flow_graph_builder_->next_block_id_); |
| 3457 bool found = flow_graph_builder_->graph_entry_->PruneUnreachable( |
| 3458 flow_graph_builder_->graph_entry_, NULL, flow_graph_builder_->osr_id_, |
| 3459 block_marks); |
| 3460 ASSERT(found); |
| 3461 } |
| 3462 return new (Z) |
| 3463 FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_, |
| 3464 flow_graph_builder_->next_block_id_ - 1); |
| 3465 } |
| 3466 |
| 3467 Fragment StreamingFlowGraphBuilder::BuildGetMainClosure() { |
| 3468 // _getMainClosure in dart:_builtin. Compile that one specially here. |
| 3469 const dart::Library& builtin = |
| 3470 dart::Library::Handle(Z, I->object_store()->builtin_library()); |
| 3471 const Object& main = |
| 3472 Object::Handle(Z, builtin.LookupObjectAllowPrivate(dart::String::Handle( |
| 3473 Z, dart::String::New("main")))); |
| 3474 if (main.IsField()) { |
| 3475 UNIMPLEMENTED(); |
| 3476 } else if (main.IsFunction()) { |
| 3477 const Function& function = Function::Cast(main); |
| 3478 if (function.kind() == RawFunction::kRegularFunction) { |
| 3479 const Function& closure_function = |
| 3480 Function::Handle(Z, function.ImplicitClosureFunction()); |
| 3481 const Instance& closure = |
| 3482 Instance::ZoneHandle(Z, closure_function.ImplicitStaticClosure()); |
| 3483 return Constant(closure) + Return(TokenPosition::kNoSource); |
| 3484 } else { |
| 3485 UNIMPLEMENTED(); |
| 3486 } |
| 3487 } else { |
| 3488 UNIMPLEMENTED(); |
| 3489 } |
| 3490 return Fragment(); |
| 3491 } |
| 3492 |
| 3493 FlowGraph* StreamingFlowGraphBuilder::BuildGraph(intptr_t kernel_offset) { |
| 3494 const Function& function = parsed_function()->function(); |
| 3495 |
| 3496 // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used |
| 3497 // e.g. for type translation. |
| 3498 const dart::Class& klass = |
| 3499 dart::Class::Handle(zone_, parsed_function()->function().Owner()); |
| 3500 bool is_in_builtin_library_toplevel = |
| 3501 klass.library() == I->object_store()->builtin_library() && |
| 3502 klass.IsTopLevel(); |
| 3503 |
| 3504 Function& outermost_function = Function::Handle(Z); |
| 3505 intptr_t outermost_kernel_offset = -1; |
| 3506 intptr_t parent_class_offset = -1; |
| 3507 DiscoverEnclosingElements(Z, function, &outermost_function, |
| 3508 &outermost_kernel_offset, &parent_class_offset); |
| 3509 // Use [klass]/[kernel_class] as active class. Type parameters will get |
| 3510 // resolved via [kernel_class] unless we are nested inside a static factory |
| 3511 // in which case we will use [member]. |
| 3512 intptr_t class_type_parameters = 0; |
| 3513 intptr_t class_type_parameters_offset_start = -1; |
| 3514 if (parent_class_offset > 0) { |
| 3515 GetTypeParameterInfoForClass(parent_class_offset, &class_type_parameters, |
| 3516 &class_type_parameters_offset_start); |
| 3517 } |
| 3518 |
| 3519 ActiveClassScope active_class_scope(active_class(), class_type_parameters, |
| 3520 class_type_parameters_offset_start, |
| 3521 &klass); |
| 3522 |
| 3523 bool member_is_procedure = false; |
| 3524 bool is_factory_procedure = false; |
| 3525 intptr_t member_type_parameters = 0; |
| 3526 intptr_t member_type_parameters_offset_start = -1; |
| 3527 GetTypeParameterInfoForPossibleProcedure( |
| 3528 outermost_kernel_offset, &member_is_procedure, &is_factory_procedure, |
| 3529 &member_type_parameters, &member_type_parameters_offset_start); |
| 3530 |
| 3531 ActiveMemberScope active_member(active_class(), member_is_procedure, |
| 3532 is_factory_procedure, member_type_parameters, |
| 3533 member_type_parameters_offset_start); |
| 3534 |
| 3535 // The IR builder will create its own local variables and scopes, and it |
| 3536 // will not need an AST. The code generator will assume that there is a |
| 3537 // local variable stack slot allocated for the current context and (I |
| 3538 // think) that the runtime will expect it to be at a fixed offset which |
| 3539 // requires allocating an unused expression temporary variable. |
| 3540 set_scopes(parsed_function()->EnsureKernelScopes()); |
| 3541 |
2687 SetOffset(kernel_offset); | 3542 SetOffset(kernel_offset); |
2688 return BuildExpression(); // read expression. | 3543 |
2689 } | 3544 switch (function.kind()) { |
| 3545 case RawFunction::kClosureFunction: |
| 3546 case RawFunction::kRegularFunction: |
| 3547 case RawFunction::kGetterFunction: |
| 3548 case RawFunction::kSetterFunction: { |
| 3549 ReadUntilFunctionNode(); // read until function node. |
| 3550 return function.IsImplicitClosureFunction() |
| 3551 ? BuildGraphOfImplicitClosureFunction(function) |
| 3552 : BuildGraphOfFunction(is_in_builtin_library_toplevel); |
| 3553 } |
| 3554 case RawFunction::kConstructor: { |
| 3555 bool is_factory = function.IsFactory(); |
| 3556 if (is_factory) { |
| 3557 ReadUntilFunctionNode(); // read until function node. |
| 3558 return BuildGraphOfFunction(is_in_builtin_library_toplevel); |
| 3559 } else { |
| 3560 // Constructor: Pass offset to parent class. |
| 3561 return BuildGraphOfFunction( |
| 3562 is_in_builtin_library_toplevel, |
| 3563 ReadUntilFunctionNode()); // read until function node. |
| 3564 } |
| 3565 } |
| 3566 case RawFunction::kImplicitGetter: |
| 3567 case RawFunction::kImplicitStaticFinalGetter: |
| 3568 case RawFunction::kImplicitSetter: { |
| 3569 return IsStaticInitializer(function, Z) |
| 3570 ? BuildGraphOfStaticFieldInitializer() |
| 3571 : BuildGraphOfFieldAccessor(scopes()->setter_value); |
| 3572 } |
| 3573 case RawFunction::kMethodExtractor: |
| 3574 return flow_graph_builder_->BuildGraphOfMethodExtractor(function); |
| 3575 case RawFunction::kNoSuchMethodDispatcher: |
| 3576 return flow_graph_builder_->BuildGraphOfNoSuchMethodDispatcher(function); |
| 3577 case RawFunction::kInvokeFieldDispatcher: |
| 3578 return flow_graph_builder_->BuildGraphOfInvokeFieldDispatcher(function); |
| 3579 case RawFunction::kSignatureFunction: |
| 3580 case RawFunction::kIrregexpFunction: |
| 3581 break; |
| 3582 } |
| 3583 UNREACHABLE(); |
| 3584 return NULL; |
| 3585 } |
| 3586 |
2690 | 3587 |
2691 Fragment StreamingFlowGraphBuilder::BuildStatementAt(intptr_t kernel_offset) { | 3588 Fragment StreamingFlowGraphBuilder::BuildStatementAt(intptr_t kernel_offset) { |
2692 SetOffset(kernel_offset); | 3589 SetOffset(kernel_offset); |
2693 return BuildStatement(); // read statement. | 3590 return BuildStatement(); // read statement. |
2694 } | 3591 } |
2695 | 3592 |
2696 Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) { | 3593 Fragment StreamingFlowGraphBuilder::BuildExpression(TokenPosition* position) { |
2697 uint8_t payload = 0; | 3594 uint8_t payload = 0; |
2698 Tag tag = ReadTag(&payload); // read tag. | 3595 Tag tag = ReadTag(&payload); // read tag. |
2699 switch (tag) { | 3596 switch (tag) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2755 return BuildThrow(position); | 3652 return BuildThrow(position); |
2756 case kListLiteral: | 3653 case kListLiteral: |
2757 return BuildListLiteral(false, position); | 3654 return BuildListLiteral(false, position); |
2758 case kConstListLiteral: | 3655 case kConstListLiteral: |
2759 return BuildListLiteral(true, position); | 3656 return BuildListLiteral(true, position); |
2760 case kMapLiteral: | 3657 case kMapLiteral: |
2761 return BuildMapLiteral(false, position); | 3658 return BuildMapLiteral(false, position); |
2762 case kConstMapLiteral: | 3659 case kConstMapLiteral: |
2763 return BuildMapLiteral(true, position); | 3660 return BuildMapLiteral(true, position); |
2764 case kFunctionExpression: | 3661 case kFunctionExpression: |
2765 // TODO(jensj) | 3662 return BuildFunctionExpression(); |
2766 UNIMPLEMENTED(); | |
2767 return Fragment(); | |
2768 case kLet: | 3663 case kLet: |
2769 return BuildLet(position); | 3664 return BuildLet(position); |
2770 case kBigIntLiteral: | 3665 case kBigIntLiteral: |
2771 return BuildBigIntLiteral(position); | 3666 return BuildBigIntLiteral(position); |
2772 case kStringLiteral: | 3667 case kStringLiteral: |
2773 return BuildStringLiteral(position); | 3668 return BuildStringLiteral(position); |
2774 case kSpecialIntLiteral: | 3669 case kSpecialIntLiteral: |
2775 return BuildIntLiteral(payload, position); | 3670 return BuildIntLiteral(payload, position); |
2776 case kNegativeIntLiteral: | 3671 case kNegativeIntLiteral: |
2777 return BuildIntLiteral(true, position); | 3672 return BuildIntLiteral(true, position); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2829 return BuildReturnStatement(); | 3724 return BuildReturnStatement(); |
2830 case kTryCatch: | 3725 case kTryCatch: |
2831 return BuildTryCatch(); | 3726 return BuildTryCatch(); |
2832 case kTryFinally: | 3727 case kTryFinally: |
2833 return BuildTryFinally(); | 3728 return BuildTryFinally(); |
2834 case kYieldStatement: | 3729 case kYieldStatement: |
2835 return BuildYieldStatement(); | 3730 return BuildYieldStatement(); |
2836 case kVariableDeclaration: | 3731 case kVariableDeclaration: |
2837 return BuildVariableDeclaration(); | 3732 return BuildVariableDeclaration(); |
2838 case kFunctionDeclaration: | 3733 case kFunctionDeclaration: |
2839 // TODO(jensj) | 3734 return BuildFunctionDeclaration(); |
2840 UNIMPLEMENTED(); | |
2841 return Fragment(); | |
2842 default: | 3735 default: |
2843 UNREACHABLE(); | 3736 UNREACHABLE(); |
2844 } | 3737 } |
2845 return Fragment(); | 3738 return Fragment(); |
2846 } | 3739 } |
2847 | 3740 |
2848 intptr_t StreamingFlowGraphBuilder::ReaderOffset() { | 3741 intptr_t StreamingFlowGraphBuilder::ReaderOffset() { |
2849 return reader_->offset(); | 3742 return reader_->offset(); |
2850 } | 3743 } |
2851 | 3744 |
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3347 void StreamingFlowGraphBuilder::SkipFunctionNode() { | 4240 void StreamingFlowGraphBuilder::SkipFunctionNode() { |
3348 Tag tag = ReadTag(); // read tag. | 4241 Tag tag = ReadTag(); // read tag. |
3349 ASSERT(tag == kFunctionNode); | 4242 ASSERT(tag == kFunctionNode); |
3350 | 4243 |
3351 ReadPosition(); // read position. | 4244 ReadPosition(); // read position. |
3352 ReadPosition(); // read end position. | 4245 ReadPosition(); // read end position. |
3353 ReadByte(); // read async marker. | 4246 ReadByte(); // read async marker. |
3354 ReadByte(); // read dart async marker. | 4247 ReadByte(); // read dart async marker. |
3355 SkipTypeParametersList(); // read type_parameters. | 4248 SkipTypeParametersList(); // read type_parameters. |
3356 ReadUInt(); // read required_parameter_count. | 4249 ReadUInt(); // read required_parameter_count. |
| 4250 ReadUInt(); // read total parameter count. |
3357 | 4251 |
3358 SkipListOfVariableDeclarations(); // read list of positionals. | 4252 SkipListOfVariableDeclarations(); // read list of positionals. |
3359 SkipListOfVariableDeclarations(); // read list of named. | 4253 SkipListOfVariableDeclarations(); // read list of named. |
3360 SkipDartType(); // read return type. | 4254 SkipDartType(); // read return type. |
3361 | 4255 |
3362 if (ReadTag() == kSomething) { | 4256 if (ReadTag() == kSomething) { |
3363 SkipStatement(); // Read body | 4257 SkipStatement(); // Read body |
3364 } | 4258 } |
3365 } | 4259 } |
3366 | 4260 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3470 } | 4364 } |
3471 | 4365 |
3472 ActiveClass* StreamingFlowGraphBuilder::active_class() { | 4366 ActiveClass* StreamingFlowGraphBuilder::active_class() { |
3473 return &flow_graph_builder_->active_class_; | 4367 return &flow_graph_builder_->active_class_; |
3474 } | 4368 } |
3475 | 4369 |
3476 ScopeBuildingResult* StreamingFlowGraphBuilder::scopes() { | 4370 ScopeBuildingResult* StreamingFlowGraphBuilder::scopes() { |
3477 return flow_graph_builder_->scopes_; | 4371 return flow_graph_builder_->scopes_; |
3478 } | 4372 } |
3479 | 4373 |
| 4374 void StreamingFlowGraphBuilder::set_scopes(ScopeBuildingResult* scope) { |
| 4375 flow_graph_builder_->scopes_ = scope; |
| 4376 } |
| 4377 |
3480 ParsedFunction* StreamingFlowGraphBuilder::parsed_function() { | 4378 ParsedFunction* StreamingFlowGraphBuilder::parsed_function() { |
3481 return flow_graph_builder_->parsed_function_; | 4379 return flow_graph_builder_->parsed_function_; |
3482 } | 4380 } |
3483 | 4381 |
3484 TryFinallyBlock* StreamingFlowGraphBuilder::try_finally_block() { | 4382 TryFinallyBlock* StreamingFlowGraphBuilder::try_finally_block() { |
3485 return flow_graph_builder_->try_finally_block_; | 4383 return flow_graph_builder_->try_finally_block_; |
3486 } | 4384 } |
3487 | 4385 |
3488 SwitchBlock* StreamingFlowGraphBuilder::switch_block() { | 4386 SwitchBlock* StreamingFlowGraphBuilder::switch_block() { |
3489 return flow_graph_builder_->switch_block_; | 4387 return flow_graph_builder_->switch_block_; |
(...skipping 1361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4851 | 5749 |
4852 const dart::Class& map_class = | 5750 const dart::Class& map_class = |
4853 dart::Class::Handle(Z, dart::Library::LookupCoreClass(Symbols::Map())); | 5751 dart::Class::Handle(Z, dart::Library::LookupCoreClass(Symbols::Map())); |
4854 const Function& factory_method = Function::ZoneHandle( | 5752 const Function& factory_method = Function::ZoneHandle( |
4855 Z, map_class.LookupFactory( | 5753 Z, map_class.LookupFactory( |
4856 dart::Library::PrivateCoreLibName(Symbols::MapLiteralFactory()))); | 5754 dart::Library::PrivateCoreLibName(Symbols::MapLiteralFactory()))); |
4857 | 5755 |
4858 return instructions + StaticCall(position, factory_method, 2); | 5756 return instructions + StaticCall(position, factory_method, 2); |
4859 } | 5757 } |
4860 | 5758 |
| 5759 Fragment StreamingFlowGraphBuilder::BuildFunctionExpression() { |
| 5760 intptr_t offset = ReaderOffset() - 1; // -1 to include tag byte. |
| 5761 return BuildFunctionNode(offset, TokenPosition::kNoSource, false, -1); |
| 5762 } |
| 5763 |
4861 Fragment StreamingFlowGraphBuilder::BuildLet(TokenPosition* position) { | 5764 Fragment StreamingFlowGraphBuilder::BuildLet(TokenPosition* position) { |
4862 if (position != NULL) *position = TokenPosition::kNoSource; | 5765 if (position != NULL) *position = TokenPosition::kNoSource; |
4863 | 5766 |
4864 Fragment instructions = BuildVariableDeclaration(); // read variable. | 5767 Fragment instructions = BuildVariableDeclaration(); // read variable. |
4865 instructions += BuildExpression(); // read body. | 5768 instructions += BuildExpression(); // read body. |
4866 return instructions; | 5769 return instructions; |
4867 } | 5770 } |
4868 | 5771 |
4869 | 5772 |
4870 Fragment StreamingFlowGraphBuilder::BuildBigIntLiteral( | 5773 Fragment StreamingFlowGraphBuilder::BuildBigIntLiteral( |
(...skipping 986 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5857 // use the position of the identifier. | 6760 // use the position of the identifier. |
5858 TokenPosition debug_position = Utils::Maximum(position, equals_position); | 6761 TokenPosition debug_position = Utils::Maximum(position, equals_position); |
5859 if (NeedsDebugStepCheck(stack(), debug_position)) { | 6762 if (NeedsDebugStepCheck(stack(), debug_position)) { |
5860 instructions = DebugStepCheck(debug_position) + instructions; | 6763 instructions = DebugStepCheck(debug_position) + instructions; |
5861 } | 6764 } |
5862 instructions += StoreLocal(position, variable); | 6765 instructions += StoreLocal(position, variable); |
5863 instructions += Drop(); | 6766 instructions += Drop(); |
5864 return instructions; | 6767 return instructions; |
5865 } | 6768 } |
5866 | 6769 |
| 6770 Fragment StreamingFlowGraphBuilder::BuildFunctionDeclaration() { |
| 6771 intptr_t offset = ReaderOffset() - 1; // -1 to include tag byte. |
| 6772 TokenPosition position = ReadPosition(); // read position. |
| 6773 intptr_t variable_offeset = ReaderOffset(); |
| 6774 SkipVariableDeclaration(); // read variable declaration. |
| 6775 |
| 6776 Fragment instructions = DebugStepCheck(position); |
| 6777 instructions += BuildFunctionNode(offset, position, true, variable_offeset); |
| 6778 instructions += StoreLocal(position, LookupVariable(variable_offeset)); |
| 6779 instructions += Drop(); |
| 6780 return instructions; |
| 6781 } |
| 6782 |
| 6783 Fragment StreamingFlowGraphBuilder::BuildFunctionNode( |
| 6784 intptr_t parent_kernel_offset, |
| 6785 TokenPosition parent_position, |
| 6786 bool declaration, |
| 6787 intptr_t variable_offeset) { |
| 6788 intptr_t offset = ReaderOffset(); |
| 6789 |
| 6790 TokenPosition position; |
| 6791 TokenPosition end_position; |
| 6792 word async_marker_word; |
| 6793 word dart_async_marker_word; |
| 6794 ReadFunctionNodeUntilTypeParameters( |
| 6795 &position, &end_position, &async_marker_word, |
| 6796 &dart_async_marker_word); // read first part of function node. |
| 6797 FunctionNode::AsyncMarker async_marker = |
| 6798 static_cast<FunctionNode::AsyncMarker>(async_marker_word); |
| 6799 FunctionNode::AsyncMarker dart_async_marker = |
| 6800 static_cast<FunctionNode::AsyncMarker>(dart_async_marker_word); |
| 6801 |
| 6802 if (declaration) { |
| 6803 position = parent_position; |
| 6804 } |
| 6805 if (!position.IsReal()) { |
| 6806 // Positions has to be unique in regards to the parent. |
| 6807 // A non-real at this point is probably -1, we cannot blindly use that |
| 6808 // as others might use it too. Create a new dummy non-real TokenPosition. |
| 6809 position = TokenPosition(offset).ToSynthetic(); |
| 6810 } |
| 6811 |
| 6812 SkipTypeParametersList(); // read type parameters. |
| 6813 |
| 6814 // The VM has a per-isolate table of functions indexed by the enclosing |
| 6815 // function and token position. |
| 6816 Function& function = Function::ZoneHandle(Z); |
| 6817 bool read_rest_of_function_node = false; |
| 6818 |
| 6819 // NOTE: This is not TokenPosition in the general sense! |
| 6820 function = I->LookupClosureFunction(parsed_function()->function(), position); |
| 6821 if (function.IsNull()) { |
| 6822 for (intptr_t i = 0; i < scopes()->function_scopes.length(); ++i) { |
| 6823 if (scopes()->function_scopes[i].kernel_offset != offset) { |
| 6824 continue; |
| 6825 } |
| 6826 |
| 6827 const dart::String* name; |
| 6828 if (!declaration) { |
| 6829 name = &Symbols::AnonymousClosure(); |
| 6830 } else { |
| 6831 name = &H.DartSymbol(GetNameFromVariableDeclaration(variable_offeset)); |
| 6832 } |
| 6833 // NOTE: This is not TokenPosition in the general sense! |
| 6834 function = Function::NewClosureFunction( |
| 6835 *name, parsed_function()->function(), position); |
| 6836 |
| 6837 function.set_is_debuggable(dart_async_marker == FunctionNode::kSync); |
| 6838 switch (dart_async_marker) { |
| 6839 case FunctionNode::kSyncStar: |
| 6840 function.set_modifier(RawFunction::kSyncGen); |
| 6841 break; |
| 6842 case FunctionNode::kAsync: |
| 6843 function.set_modifier(RawFunction::kAsync); |
| 6844 function.set_is_inlinable(!FLAG_causal_async_stacks); |
| 6845 break; |
| 6846 case FunctionNode::kAsyncStar: |
| 6847 function.set_modifier(RawFunction::kAsyncGen); |
| 6848 function.set_is_inlinable(!FLAG_causal_async_stacks); |
| 6849 break; |
| 6850 default: |
| 6851 // no special modifier |
| 6852 break; |
| 6853 } |
| 6854 function.set_is_generated_body(async_marker == |
| 6855 FunctionNode::kSyncYielding); |
| 6856 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) { |
| 6857 function.set_is_inlinable(!FLAG_causal_async_stacks); |
| 6858 } |
| 6859 |
| 6860 function.set_end_token_pos(end_position); |
| 6861 LocalScope* scope = scopes()->function_scopes[i].scope; |
| 6862 const ContextScope& context_scope = ContextScope::Handle( |
| 6863 Z, scope->PreserveOuterScope(flow_graph_builder_->context_depth_)); |
| 6864 function.set_context_scope(context_scope); |
| 6865 function.set_kernel_offset(offset); |
| 6866 // Read rest of function node. |
| 6867 SetupFunctionParameters(dart::Class::Handle(Z), function, |
| 6868 false, // is_method |
| 6869 true); // is_closure |
| 6870 read_rest_of_function_node = true; |
| 6871 // Finalize function type. |
| 6872 Type& signature_type = Type::Handle(Z, function.SignatureType()); |
| 6873 signature_type ^= |
| 6874 ClassFinalizer::FinalizeType(*active_class()->klass, signature_type); |
| 6875 function.SetSignatureType(signature_type); |
| 6876 |
| 6877 I->AddClosureFunction(function); |
| 6878 break; |
| 6879 } |
| 6880 } |
| 6881 |
| 6882 if (!read_rest_of_function_node) { |
| 6883 ReadUInt(); // read required_parameter_count. |
| 6884 ReadUInt(); // read total parameter count. |
| 6885 SkipListOfVariableDeclarations(); // read list of positionals. |
| 6886 SkipListOfVariableDeclarations(); // read list of named. |
| 6887 SkipDartType(); // read return type. |
| 6888 if (ReadTag() == kSomething) { // read first part of body. |
| 6889 SkipStatement(); // read body. |
| 6890 } |
| 6891 } |
| 6892 |
| 6893 const dart::Class& closure_class = |
| 6894 dart::Class::ZoneHandle(Z, I->object_store()->closure_class()); |
| 6895 ASSERT(!closure_class.IsNull()); |
| 6896 Fragment instructions = |
| 6897 flow_graph_builder_->AllocateObject(closure_class, function); |
| 6898 LocalVariable* closure = MakeTemporary(); |
| 6899 |
| 6900 // TODO(27590): Generic closures need type arguments. |
| 6901 |
| 6902 // Store the function and the context in the closure. |
| 6903 instructions += LoadLocal(closure); |
| 6904 instructions += Constant(function); |
| 6905 instructions += flow_graph_builder_->StoreInstanceField( |
| 6906 TokenPosition::kNoSource, Closure::function_offset()); |
| 6907 |
| 6908 instructions += LoadLocal(closure); |
| 6909 instructions += LoadLocal(parsed_function()->current_context_var()); |
| 6910 instructions += flow_graph_builder_->StoreInstanceField( |
| 6911 TokenPosition::kNoSource, Closure::context_offset()); |
| 6912 |
| 6913 return instructions; |
| 6914 } |
| 6915 |
| 6916 |
| 6917 void StreamingFlowGraphBuilder::SetupFunctionParameters( |
| 6918 const dart::Class& klass, |
| 6919 const dart::Function& function, |
| 6920 bool is_method, |
| 6921 bool is_closure) { |
| 6922 ASSERT(!(is_method && is_closure)); |
| 6923 bool is_factory = function.IsFactory(); |
| 6924 intptr_t extra_parameters = (is_method || is_closure || is_factory) ? 1 : 0; |
| 6925 |
| 6926 intptr_t required_parameter_count = |
| 6927 ReadUInt(); // read required_parameter_count. |
| 6928 intptr_t total_parameter_count = ReadUInt(); // read total parameter count. |
| 6929 intptr_t positional_parameters_count = ReadListLength(); // read list length. |
| 6930 intptr_t named_parameters_count = |
| 6931 total_parameter_count - positional_parameters_count; |
| 6932 |
| 6933 function.set_num_fixed_parameters(extra_parameters + |
| 6934 required_parameter_count); |
| 6935 if (named_parameters_count > 0) { |
| 6936 function.SetNumOptionalParameters(named_parameters_count, false); |
| 6937 } else { |
| 6938 function.SetNumOptionalParameters( |
| 6939 positional_parameters_count - required_parameter_count, true); |
| 6940 } |
| 6941 intptr_t num_parameters = extra_parameters + total_parameter_count; |
| 6942 function.set_parameter_types( |
| 6943 Array::Handle(Z, Array::New(num_parameters, Heap::kOld))); |
| 6944 function.set_parameter_names( |
| 6945 Array::Handle(Z, Array::New(num_parameters, Heap::kOld))); |
| 6946 intptr_t pos = 0; |
| 6947 if (is_method) { |
| 6948 ASSERT(!klass.IsNull()); |
| 6949 function.SetParameterTypeAt(pos, H.GetCanonicalType(klass)); |
| 6950 function.SetParameterNameAt(pos, Symbols::This()); |
| 6951 pos++; |
| 6952 } else if (is_closure) { |
| 6953 function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); |
| 6954 function.SetParameterNameAt(pos, Symbols::ClosureParameter()); |
| 6955 pos++; |
| 6956 } else if (is_factory) { |
| 6957 function.SetParameterTypeAt(pos, AbstractType::dynamic_type()); |
| 6958 function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter()); |
| 6959 pos++; |
| 6960 } |
| 6961 |
| 6962 for (intptr_t i = 0; i < positional_parameters_count; ++i, ++pos) { |
| 6963 // Read ith variable declaration. |
| 6964 ReadPosition(); // read position. |
| 6965 ReadPosition(); // read equals position. |
| 6966 ReadFlags(); // read flags. |
| 6967 StringIndex name = ReadStringReference(); // read name index. |
| 6968 const AbstractType& type = T.BuildTypeWithoutFinalization(); // read type. |
| 6969 Tag tag = ReadTag(); // read (first part of) initializer. |
| 6970 if (tag == kSomething) { |
| 6971 SkipExpression(); // read (actual) initializer. |
| 6972 } |
| 6973 |
| 6974 function.SetParameterTypeAt( |
| 6975 pos, type.IsMalformed() ? Type::dynamic_type() : type); |
| 6976 function.SetParameterNameAt(pos, H.DartSymbol(name)); |
| 6977 } |
| 6978 |
| 6979 intptr_t named_parameters_count_check = |
| 6980 ReadListLength(); // read list length. |
| 6981 ASSERT(named_parameters_count_check == named_parameters_count); |
| 6982 for (intptr_t i = 0; i < named_parameters_count; ++i, ++pos) { |
| 6983 // Read ith variable declaration. |
| 6984 ReadPosition(); // read position. |
| 6985 ReadPosition(); // read equals position. |
| 6986 ReadFlags(); // read flags. |
| 6987 StringIndex name = ReadStringReference(); // read name index. |
| 6988 const AbstractType& type = T.BuildTypeWithoutFinalization(); // read type. |
| 6989 Tag tag = ReadTag(); // read (first part of) initializer. |
| 6990 if (tag == kSomething) { |
| 6991 SkipExpression(); // read (actual) initializer. |
| 6992 } |
| 6993 |
| 6994 function.SetParameterTypeAt( |
| 6995 pos, type.IsMalformed() ? Type::dynamic_type() : type); |
| 6996 function.SetParameterNameAt(pos, H.DartSymbol(name)); |
| 6997 } |
| 6998 |
| 6999 // The result type for generative constructors has already been set. |
| 7000 if (!function.IsGenerativeConstructor()) { |
| 7001 const AbstractType& return_type = |
| 7002 T.BuildTypeWithoutFinalization(); // read return type. |
| 7003 function.set_result_type(return_type.IsMalformed() ? Type::dynamic_type() |
| 7004 : return_type); |
| 7005 } else { |
| 7006 SkipDartType(); // read return type. |
| 7007 } |
| 7008 |
| 7009 if (ReadTag() == kSomething) { // read first part of body. |
| 7010 SkipStatement(); // read body. |
| 7011 } |
| 7012 } |
| 7013 |
| 7014 RawObject* StreamingFlowGraphBuilder::BuildParameterDescriptor( |
| 7015 intptr_t kernel_offset) { |
| 7016 SetOffset(kernel_offset); |
| 7017 ReadUntilFunctionNode(); // read until function node. |
| 7018 ReadFunctionNodeUntilTypeParameters( |
| 7019 &unused_tokenposition, &unused_tokenposition, &unused_word, |
| 7020 &unused_word); // read first part of function node. |
| 7021 SkipTypeParametersList(); // read type_parameters. |
| 7022 |
| 7023 ReadUInt(); // read required_parameter_count. |
| 7024 intptr_t param_count = ReadUInt(); // read total parameter count. |
| 7025 intptr_t positional_count = ReadListLength(); // read list length. |
| 7026 intptr_t named_parameters_count = param_count - positional_count; |
| 7027 |
| 7028 const Array& param_descriptor = Array::Handle( |
| 7029 Array::New(param_count * Parser::kParameterEntrySize, Heap::kOld)); |
| 7030 for (intptr_t i = 0; i < param_count; ++i) { |
| 7031 const intptr_t entry_start = i * Parser::kParameterEntrySize; |
| 7032 |
| 7033 if (i == positional_count) { |
| 7034 intptr_t named_parameters_count_check = |
| 7035 ReadListLength(); // read list length. |
| 7036 ASSERT(named_parameters_count_check == named_parameters_count); |
| 7037 } |
| 7038 |
| 7039 // Read ith variable declaration. |
| 7040 ReadPosition(); // read position. |
| 7041 ReadPosition(); // read equals position. |
| 7042 word flags = ReadFlags(); // read flags. |
| 7043 bool is_final = (flags & VariableDeclaration::kFlagFinal) == |
| 7044 VariableDeclaration::kFlagFinal; |
| 7045 param_descriptor.SetAt(entry_start + Parser::kParameterIsFinalOffset, |
| 7046 is_final ? Bool::True() : Bool::False()); |
| 7047 |
| 7048 SkipStringReference(); // read name index. |
| 7049 SkipDartType(); // read type. |
| 7050 Tag tag = ReadTag(); // read (first part of) initializer. |
| 7051 if (tag == kSomething) { |
| 7052 // this will (potentially) read the initializer, but reset the position. |
| 7053 Instance& constant = |
| 7054 constant_evaluator_.EvaluateExpression(ReaderOffset()); |
| 7055 SkipExpression(); // read (actual) initializer. |
| 7056 param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset, |
| 7057 constant); |
| 7058 } else { |
| 7059 param_descriptor.SetAt(entry_start + Parser::kParameterDefaultValueOffset, |
| 7060 Object::null_instance()); |
| 7061 } |
| 7062 |
| 7063 param_descriptor.SetAt(entry_start + Parser::kParameterMetadataOffset, |
| 7064 /* Issue(28434): Missing parameter metadata. */ |
| 7065 Object::null_instance()); |
| 7066 } |
| 7067 return param_descriptor.raw(); |
| 7068 } |
| 7069 |
| 7070 RawObject* StreamingFlowGraphBuilder::EvaluateMetadata(intptr_t kernel_offset) { |
| 7071 SetOffset(kernel_offset); |
| 7072 const Tag tag = PeekTag(); |
| 7073 |
| 7074 if (tag == kClass) { |
| 7075 Tag tag = ReadTag(); // read tag. |
| 7076 ASSERT(tag == kClass); |
| 7077 SkipCanonicalNameReference(); // read canonical name reference. |
| 7078 ReadPosition(); // read position. |
| 7079 ReadByte(); // read is_abstract |
| 7080 SkipStringReference(); // read name_index. |
| 7081 ReadUInt(); // read source_uri_index. |
| 7082 // SkipListOfExpressions(); // read annotations. |
| 7083 } else if (tag == kProcedure) { |
| 7084 Tag tag = ReadTag(); // read tag. |
| 7085 ASSERT(tag == kProcedure); |
| 7086 SkipCanonicalNameReference(); // read canonical name reference. |
| 7087 ReadPosition(); // read position. |
| 7088 ReadPosition(); // read end position. |
| 7089 ReadByte(); // read kind. |
| 7090 ReadFlags(); // read flags. |
| 7091 ReadUInt(); // read parent class binary offset. |
| 7092 SkipName(); // read name, |
| 7093 ReadUInt(); // read source_uri_index. |
| 7094 // SkipListOfExpressions(); // read annotations. |
| 7095 } else if (tag == kField) { |
| 7096 ReadFieldUntilAnnotation(&unused_nameindex, &unused_tokenposition, |
| 7097 &unused_tokenposition, &unused_word, |
| 7098 &unused_intptr); |
| 7099 // SkipListOfExpressions(); // read annotations. |
| 7100 } else if (tag == kConstructor) { |
| 7101 Tag tag = ReadTag(); |
| 7102 ASSERT(tag == kConstructor); |
| 7103 SkipCanonicalNameReference(); // read canonical name reference. |
| 7104 ReadPosition(); // read position. |
| 7105 ReadPosition(); // read end position. |
| 7106 ReadFlags(); // read flags. |
| 7107 ReadUInt(); // parent class binary offset. |
| 7108 SkipName(); // read name. |
| 7109 // SkipListOfExpressions(); // read annotations. |
| 7110 } else { |
| 7111 FATAL("No support for metadata on this type of kernel node\n"); |
| 7112 } |
| 7113 |
| 7114 intptr_t list_length = ReadListLength(); // read list length. |
| 7115 const Array& metadata_values = Array::Handle(Z, Array::New(list_length)); |
| 7116 for (intptr_t i = 0; i < list_length; ++i) { |
| 7117 // this will (potentially) read the expression, but reset the position. |
| 7118 Instance& value = constant_evaluator_.EvaluateExpression(ReaderOffset()); |
| 7119 SkipExpression(); // read (actual) initializer. |
| 7120 metadata_values.SetAt(i, value); |
| 7121 } |
| 7122 |
| 7123 return metadata_values.raw(); |
| 7124 } |
| 7125 |
5867 } // namespace kernel | 7126 } // namespace kernel |
5868 } // namespace dart | 7127 } // namespace dart |
5869 | 7128 |
5870 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 7129 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
OLD | NEW |