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