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/longjump.h" | |
7 #include "vm/object_store.h" | 8 #include "vm/object_store.h" |
8 | 9 |
9 #if !defined(DART_PRECOMPILED_RUNTIME) | 10 #if !defined(DART_PRECOMPILED_RUNTIME) |
10 | 11 |
11 namespace dart { | 12 namespace dart { |
12 namespace kernel { | 13 namespace kernel { |
13 | 14 |
14 #define Z (zone_) | 15 #define Z (zone_) |
15 #define H (translation_helper_) | 16 #define H (translation_helper_) |
17 #define T (type_translator_) | |
16 #define I Isolate::Current() | 18 #define I Isolate::Current() |
17 | 19 |
20 | |
21 AbstractType& StreamingDartTypeTranslator::BuildType() { | |
22 BuildTypeInternal(); | |
23 | |
24 // We return a new `ZoneHandle` here on purpose: The intermediate language | |
25 // instructions do not make a copy of the handle, so we do it. | |
26 return dart::AbstractType::ZoneHandle(Z, result_.raw()); | |
27 } | |
28 | |
29 void StreamingDartTypeTranslator::BuildTypeInternal() { | |
30 Tag tag = builder_->ReadTag(); | |
31 switch (tag) { | |
32 case kInvalidType: | |
33 result_ = ClassFinalizer::NewFinalizedMalformedType( | |
34 Error::Handle(Z), // No previous error. | |
35 dart::Script::Handle(Z, dart::Script::null()), | |
36 TokenPosition::kNoSource, "[InvalidType] in Kernel IR."); | |
37 break; | |
38 case kDynamicType: | |
39 result_ = Object::dynamic_type().raw(); | |
40 break; | |
41 case kVoidType: | |
42 result_ = Object::void_type().raw(); | |
43 break; | |
44 case kInterfaceType: | |
45 BuildInterfaceType(false); | |
46 break; | |
47 case kSimpleInterfaceType: | |
48 BuildInterfaceType(true); | |
49 break; | |
50 case kFunctionType: | |
51 BuildFunctionType(); | |
52 break; | |
53 case kSimpleFunctionType: | |
54 BuildSimpleFunctionType(); | |
55 break; | |
56 case kTypeParameterType: | |
57 BuildTypeParameterType(); | |
58 break; | |
59 default: | |
60 UNREACHABLE(); | |
61 } | |
62 } | |
63 | |
64 void StreamingDartTypeTranslator::BuildInterfaceType(bool simple) { | |
65 // NOTE: That an interface type like `T<A, B>` is considered to be | |
66 // malformed iff `T` is malformed. | |
67 // => We therefore ignore errors in `A` or `B`. | |
68 | |
69 CanonicalName* klass_name = | |
70 builder_->GetCanonicalName(builder_->ReadUInt()); // read klass_name. | |
71 | |
72 intptr_t length; | |
73 if (simple) { | |
74 length = 0; | |
75 } else { | |
76 length = builder_->ReadListLength(); // read type_arguments list length. | |
77 } | |
78 const TypeArguments& type_arguments = BuildTypeArguments(length); | |
79 | |
80 dart::Object& klass = | |
81 dart::Object::Handle(Z, H.LookupClassByKernelClass(klass_name)); | |
82 result_ = Type::New(klass, type_arguments, TokenPosition::kNoSource); | |
83 if (finalize_) { | |
84 ASSERT(active_class_->klass != NULL); | |
85 result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_); | |
86 } | |
87 } | |
88 | |
89 void StreamingDartTypeTranslator::BuildFunctionType() { | |
jensj
2017/05/04 10:13:05
BuildFunctionType and BuildSimpleFunctionType are
| |
90 intptr_t list_length = | |
91 builder_->ReadListLength(); // read type_parameters list length | |
92 intptr_t* type_parameters = new intptr_t[list_length]; | |
93 for (int i = 0; i < list_length; ++i) { | |
94 type_parameters[i] = builder_->ReaderOffset(); | |
95 builder_->ReadUInt(); // read string index (name). | |
96 builder_->SkipDartType(); // read dart type. | |
97 } | |
98 | |
99 // The spec describes in section "19.1 Static Types": | |
100 // | |
101 // Any use of a malformed type gives rise to a static warning. A | |
102 // malformed type is then interpreted as dynamic by the static type | |
103 // checker and the runtime unless explicitly specified otherwise. | |
104 // | |
105 // So we convert malformed return/parameter types to `dynamic`. | |
106 TypeParameterScope scope(this, type_parameters, list_length); | |
107 | |
108 Function& signature_function = Function::ZoneHandle( | |
109 Z, Function::NewSignatureFunction(*active_class_->klass, | |
110 TokenPosition::kNoSource)); | |
111 | |
112 const intptr_t required_count = | |
113 builder_->ReadUInt(); // read required parameter count. | |
114 const intptr_t all_count = | |
115 builder_->ReadUInt(); // read total parameter count. | |
116 | |
117 const Array& parameter_types = | |
118 Array::Handle(Z, Array::New(1 + all_count, Heap::kOld)); | |
119 signature_function.set_parameter_types(parameter_types); | |
120 const Array& parameter_names = | |
121 Array::Handle(Z, Array::New(1 + all_count, Heap::kOld)); | |
122 signature_function.set_parameter_names(parameter_names); | |
123 | |
124 const intptr_t positional_count = | |
125 builder_->ReadListLength(); // read positional_parameters list length. | |
126 intptr_t pos = 0; | |
127 parameter_types.SetAt(pos, AbstractType::dynamic_type()); | |
128 parameter_names.SetAt(pos, H.DartSymbol("_receiver_")); | |
129 ++pos; | |
130 for (intptr_t i = 0; i < positional_count; ++i, ++pos) { | |
131 BuildTypeInternal(); // read ith positional parameter. | |
132 if (result_.IsMalformed()) { | |
133 result_ = AbstractType::dynamic_type().raw(); | |
134 } | |
135 parameter_types.SetAt(pos, result_); | |
136 parameter_names.SetAt(pos, H.DartSymbol("noname")); | |
137 } | |
138 | |
139 const intptr_t named_count = | |
140 builder_->ReadListLength(); // read named_parameters list length. | |
141 | |
142 // The additional first parameter is the receiver type (set to dynamic). | |
143 signature_function.set_num_fixed_parameters(1 + required_count); | |
144 signature_function.SetNumOptionalParameters( | |
145 all_count - required_count, positional_count > required_count); | |
146 | |
147 for (intptr_t i = 0; i < named_count; ++i, ++pos) { | |
148 // read string reference (i.e. named_parameters[i].name). | |
149 dart::String& name = H.DartSymbol(builder_->ReadUInt()); | |
150 BuildTypeInternal(); // read named_parameters[i].type. | |
151 if (result_.IsMalformed()) { | |
152 result_ = AbstractType::dynamic_type().raw(); | |
153 } | |
154 parameter_types.SetAt(pos, result_); | |
155 parameter_names.SetAt(pos, name); | |
156 } | |
157 | |
158 BuildTypeInternal(); // read return type. | |
159 if (result_.IsMalformed()) { | |
160 result_ = AbstractType::dynamic_type().raw(); | |
161 } | |
162 signature_function.set_result_type(result_); | |
163 | |
164 Type& signature_type = | |
165 Type::ZoneHandle(Z, signature_function.SignatureType()); | |
166 | |
167 if (finalize_) { | |
168 signature_type ^= | |
169 ClassFinalizer::FinalizeType(*active_class_->klass, signature_type); | |
170 // Do not refer to signature_function anymore, since it may have been | |
171 // replaced during canonicalization. | |
172 signature_function = Function::null(); | |
173 } | |
174 | |
175 result_ = signature_type.raw(); | |
176 } | |
177 | |
178 void StreamingDartTypeTranslator::BuildSimpleFunctionType() { | |
179 const intptr_t positional_count = | |
180 builder_->ReadListLength(); // read positional_parameters length. | |
181 | |
182 // The spec describes in section "19.1 Static Types": | |
183 // | |
184 // Any use of a malformed type gives rise to a static warning. A | |
185 // malformed type is then interpreted as dynamic by the static type | |
186 // checker and the runtime unless explicitly specified otherwise. | |
187 // | |
188 // So we convert malformed return/parameter types to `dynamic`. | |
189 TypeParameterScope scope(this, NULL, 0); | |
190 | |
191 Function& signature_function = Function::ZoneHandle( | |
192 Z, Function::NewSignatureFunction(*active_class_->klass, | |
193 TokenPosition::kNoSource)); | |
194 | |
195 // The additional first parameter is the receiver type (set to dynamic). | |
196 signature_function.set_num_fixed_parameters(1 + positional_count); | |
197 | |
198 const Array& parameter_types = | |
199 Array::Handle(Z, Array::New(1 + positional_count, Heap::kOld)); | |
200 signature_function.set_parameter_types(parameter_types); | |
201 const Array& parameter_names = | |
202 Array::Handle(Z, Array::New(1 + positional_count, Heap::kOld)); | |
203 signature_function.set_parameter_names(parameter_names); | |
204 | |
205 intptr_t pos = 0; | |
206 parameter_types.SetAt(pos, AbstractType::dynamic_type()); | |
207 parameter_names.SetAt(pos, H.DartSymbol("_receiver_")); | |
208 ++pos; | |
209 for (intptr_t i = 0; i < positional_count; ++i, ++pos) { | |
210 BuildTypeInternal(); // read ith positional parameter. | |
211 | |
212 if (result_.IsMalformed()) { | |
213 result_ = AbstractType::dynamic_type().raw(); | |
214 } | |
215 parameter_types.SetAt(pos, result_); | |
216 parameter_names.SetAt(pos, H.DartSymbol("noname")); | |
217 } | |
218 | |
219 BuildTypeInternal(); // read return type. | |
220 if (result_.IsMalformed()) { | |
221 result_ = AbstractType::dynamic_type().raw(); | |
222 } | |
223 signature_function.set_result_type(result_); | |
224 | |
225 Type& signature_type = | |
226 Type::ZoneHandle(Z, signature_function.SignatureType()); | |
227 | |
228 if (finalize_) { | |
229 signature_type ^= | |
230 ClassFinalizer::FinalizeType(*active_class_->klass, signature_type); | |
231 // Do not refer to signature_function anymore, since it may have been | |
232 // replaced during canonicalization. | |
233 signature_function = Function::null(); | |
234 } | |
235 | |
236 result_ = signature_type.raw(); | |
237 } | |
238 | |
239 static intptr_t FindTypeParameterIndex(intptr_t* parameters, | |
240 intptr_t parameters_count, | |
241 intptr_t look_for) { | |
242 for (intptr_t i = 0; i < parameters_count; ++i) { | |
243 if (look_for == parameters[i]) { | |
244 return i; | |
245 } | |
246 } | |
247 return -1; | |
248 } | |
249 | |
250 static intptr_t FindTypeParameterIndex(List<TypeParameter>* parameters, | |
251 intptr_t look_for) { | |
252 for (intptr_t i = 0; i < parameters->length(); ++i) { | |
253 if (look_for == (*parameters)[i]->kernel_offset()) { | |
254 return i; | |
255 } | |
256 } | |
257 return -1; | |
258 } | |
259 | |
260 void StreamingDartTypeTranslator::BuildTypeParameterType() { | |
261 builder_->ReadUInt(); // read parameter index. | |
262 intptr_t binary_offset = builder_->ReadUInt(); // read binary offset. | |
263 if (binary_offset == 0) { | |
264 // TODO(jensj): This doesn't appear to actually happen. | |
265 UNIMPLEMENTED(); | |
266 return; | |
267 } | |
268 | |
269 for (TypeParameterScope* scope = type_parameter_scope_; scope != NULL; | |
270 scope = scope->outer()) { | |
271 const intptr_t index = FindTypeParameterIndex( | |
272 scope->parameters(), scope->parameters_count(), binary_offset); | |
273 if (index >= 0) { | |
274 result_ ^= dart::Type::DynamicType(); | |
275 return; | |
276 } | |
277 } | |
278 | |
279 if ((active_class_->member != NULL) && active_class_->member->IsProcedure()) { | |
280 Procedure* procedure = Procedure::Cast(active_class_->member); | |
281 if ((procedure->function() != NULL) && | |
282 (procedure->function()->type_parameters().length() > 0)) { | |
283 // | |
284 // WARNING: This is a little hackish: | |
285 // | |
286 // We have a static factory constructor. The kernel IR gives the factory | |
287 // constructor function it's own type parameters (which are equal in name | |
288 // and number to the ones of the enclosing class). | |
289 // I.e., | |
290 // | |
291 // class A<T> { | |
292 // factory A.x() { return new B<T>(); } | |
293 // } | |
294 // | |
295 // is basically translated to this: | |
296 // | |
297 // class A<T> { | |
298 // static A.x<T'>() { return new B<T'>(); } | |
299 // } | |
300 // | |
301 const intptr_t index = FindTypeParameterIndex( | |
302 &procedure->function()->type_parameters(), binary_offset); | |
303 if (index >= 0) { | |
304 if (procedure->kind() == Procedure::kFactory) { | |
305 // The index of the type parameter in [parameters] is | |
306 // the same index into the `klass->type_parameters()` array. | |
307 result_ ^= dart::TypeArguments::Handle( | |
308 Z, active_class_->klass->type_parameters()) | |
309 .TypeAt(index); | |
310 } else { | |
311 result_ ^= dart::Type::DynamicType(); | |
312 } | |
313 return; | |
314 } | |
315 } | |
316 } | |
317 | |
318 ASSERT(active_class_->kernel_class != NULL); | |
319 List<TypeParameter>* parameters = | |
320 &active_class_->kernel_class->type_parameters(); | |
321 const intptr_t index = FindTypeParameterIndex(parameters, binary_offset); | |
322 if (index >= 0) { | |
323 // The index of the type parameter in [parameters] is | |
324 // the same index into the `klass->type_parameters()` array. | |
325 result_ ^= | |
326 dart::TypeArguments::Handle(Z, active_class_->klass->type_parameters()) | |
327 .TypeAt(index); | |
328 return; | |
329 } | |
330 | |
331 UNREACHABLE(); | |
332 } | |
333 | |
334 const TypeArguments& StreamingDartTypeTranslator::BuildTypeArguments( | |
335 intptr_t length) { | |
336 bool only_dynamic = true; | |
337 intptr_t offset = builder_->ReaderOffset(); | |
338 for (intptr_t i = 0; i < length; ++i) { | |
339 if (builder_->ReadTag() != kDynamicType) { // read ith type's tag. | |
340 only_dynamic = false; | |
341 builder_->SetOffset(offset); | |
342 break; | |
343 } | |
344 } | |
345 TypeArguments& type_arguments = TypeArguments::ZoneHandle(Z); | |
346 if (!only_dynamic) { | |
347 type_arguments = TypeArguments::New(length); | |
348 for (intptr_t i = 0; i < length; ++i) { | |
349 BuildTypeInternal(); // read ith type. | |
350 if (!result_.IsDynamicType()) { | |
351 only_dynamic = false; | |
352 } | |
353 if (result_.IsMalformed()) { | |
354 type_arguments = TypeArguments::null(); | |
355 return type_arguments; | |
356 } | |
357 type_arguments.SetTypeAt(i, result_); | |
358 } | |
359 | |
360 if (finalize_) { | |
361 type_arguments = type_arguments.Canonicalize(); | |
362 } | |
363 } | |
364 return type_arguments; | |
365 } | |
366 | |
367 const TypeArguments& | |
368 StreamingDartTypeTranslator::BuildInstantiatedTypeArguments( | |
369 const dart::Class& receiver_class, | |
370 intptr_t length) { | |
371 const TypeArguments& type_arguments = BuildTypeArguments(length); | |
372 if (type_arguments.IsNull()) return type_arguments; | |
373 | |
374 // We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to | |
375 // finalize the argument types. | |
376 // (This can for example make the [type_arguments] vector larger) | |
377 Type& type = Type::Handle( | |
378 Z, Type::New(receiver_class, type_arguments, TokenPosition::kNoSource)); | |
379 if (finalize_) { | |
380 type ^= | |
381 ClassFinalizer::FinalizeType(*builder_->active_class()->klass, type); | |
382 } | |
383 | |
384 const TypeArguments& instantiated_type_arguments = | |
385 TypeArguments::ZoneHandle(Z, type.arguments()); | |
386 return instantiated_type_arguments; | |
387 } | |
388 | |
389 | |
390 const Type& StreamingDartTypeTranslator::ReceiverType( | |
391 const dart::Class& klass) { | |
392 ASSERT(!klass.IsNull()); | |
393 ASSERT(!klass.IsTypedefClass()); | |
394 // Note that if klass is _Closure, the returned type will be _Closure, | |
395 // and not the signature type. | |
396 Type& type = Type::ZoneHandle(Z, klass.CanonicalType()); | |
397 if (!type.IsNull()) { | |
398 return type; | |
399 } | |
400 type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()), | |
401 klass.token_pos()); | |
402 if (klass.is_type_finalized()) { | |
403 type ^= ClassFinalizer::FinalizeType(klass, type); | |
404 klass.SetCanonicalType(type); | |
405 } | |
406 return type; | |
407 } | |
408 | |
409 | |
18 StreamingConstantEvaluator::StreamingConstantEvaluator( | 410 StreamingConstantEvaluator::StreamingConstantEvaluator( |
19 StreamingFlowGraphBuilder* builder, | 411 StreamingFlowGraphBuilder* builder, |
20 Zone* zone, | 412 Zone* zone, |
21 TranslationHelper* h, | 413 TranslationHelper* helper, |
22 DartTypeTranslator* type_translator) | 414 StreamingDartTypeTranslator* type_translator) |
23 : builder_(builder), | 415 : builder_(builder), |
24 isolate_(Isolate::Current()), | 416 isolate_(Isolate::Current()), |
25 zone_(zone), | 417 zone_(zone), |
26 translation_helper_(*h), | 418 translation_helper_(*helper), |
27 // type_translator_(*type_translator), | 419 type_translator_(*type_translator), |
28 script_(Script::Handle( | 420 script_(Script::Handle( |
29 zone, | 421 zone, |
30 builder == NULL ? Script::null() | 422 builder == NULL ? Script::null() |
31 : builder_->parsed_function()->function().script())), | 423 : builder_->parsed_function()->function().script())), |
32 result_(Instance::Handle(zone)) {} | 424 result_(Instance::Handle(zone)) {} |
33 | 425 |
34 | 426 |
35 Instance& StreamingConstantEvaluator::EvaluateExpression() { | 427 Instance& StreamingConstantEvaluator::EvaluateExpression(intptr_t offset, |
36 intptr_t offset = builder_->ReaderOffset(); | 428 bool reset_position) { |
37 if (!GetCachedConstant(offset, &result_)) { | 429 bool got_cached = GetCachedConstant(offset, &result_); |
430 if (!got_cached) { | |
431 intptr_t original_offset = builder_->ReaderOffset(); | |
432 builder_->SetOffset(offset); | |
38 uint8_t payload = 0; | 433 uint8_t payload = 0; |
39 Tag tag = builder_->ReadTag(&payload); | 434 Tag tag = builder_->ReadTag(&payload); // read tag. |
40 switch (tag) { | 435 switch (tag) { |
436 case kVariableGet: | |
437 EvaluateVariableGet(); | |
438 break; | |
439 case kSpecializedVariableGet: | |
440 EvaluateVariableGet(payload); | |
441 break; | |
442 case kPropertyGet: | |
443 EvaluatePropertyGet(); | |
444 break; | |
41 case kStaticGet: | 445 case kStaticGet: |
42 EvaluateStaticGet(); | 446 EvaluateStaticGet(); |
43 break; | 447 break; |
448 case kMethodInvocation: | |
449 EvaluateMethodInvocation(); | |
450 break; | |
451 case kStaticInvocation: | |
452 case kConstStaticInvocation: | |
453 EvaluateStaticInvocation(); | |
454 break; | |
455 case kConstructorInvocation: | |
456 case kConstConstructorInvocation: | |
457 EvaluateConstructorInvocationInternal(); | |
458 break; | |
459 case kNot: | |
460 EvaluateNot(); | |
461 break; | |
462 case kLogicalExpression: | |
463 EvaluateLogicalExpression(); | |
464 break; | |
465 case kConditionalExpression: | |
466 EvaluateConditionalExpression(); | |
467 break; | |
468 case kStringConcatenation: | |
469 EvaluateStringConcatenation(); | |
470 break; | |
44 case kSymbolLiteral: | 471 case kSymbolLiteral: |
45 EvaluateSymbolLiteral(); | 472 EvaluateSymbolLiteral(); |
46 break; | 473 break; |
474 case kTypeLiteral: | |
475 EvaluateTypeLiteral(); | |
476 break; | |
477 case kListLiteral: | |
478 case kConstListLiteral: | |
479 EvaluateListLiteralInternal(); | |
480 break; | |
481 case kMapLiteral: | |
482 case kConstMapLiteral: | |
483 EvaluateMapLiteralInternal(); | |
484 break; | |
485 case kLet: | |
486 EvaluateLet(); | |
487 break; | |
488 case kBigIntLiteral: | |
489 EvaluateBigIntLiteral(); | |
490 break; | |
491 case kStringLiteral: | |
492 EvaluateStringLiteral(); | |
493 break; | |
494 case kSpecialIntLiteral: | |
495 EvaluateIntLiteral(payload); | |
496 break; | |
497 case kNegativeIntLiteral: | |
498 EvaluateIntLiteral(true); | |
499 break; | |
500 case kPositiveIntLiteral: | |
501 EvaluateIntLiteral(false); | |
502 break; | |
47 case kDoubleLiteral: | 503 case kDoubleLiteral: |
48 EvaluateDoubleLiteral(); | 504 EvaluateDoubleLiteral(); |
49 break; | 505 break; |
506 case kTrueLiteral: | |
507 EvaluateBoolLiteral(true); | |
508 break; | |
509 case kFalseLiteral: | |
510 EvaluateBoolLiteral(false); | |
511 break; | |
512 case kNullLiteral: | |
513 EvaluateNullLiteral(); | |
514 break; | |
50 default: | 515 default: |
51 UNREACHABLE(); | 516 UNREACHABLE(); |
52 } | 517 } |
53 | 518 |
54 CacheConstantValue(offset, result_); | 519 CacheConstantValue(offset, result_); |
55 } | 520 if (reset_position) builder_->SetOffset(original_offset); |
56 // We return a new `ZoneHandle` here on purpose: The intermediate language | 521 } |
57 // instructions do not make a copy of the handle, so we do it. | 522 // We return a new `ZoneHandle` here on purpose: The intermediate language |
58 return dart::Instance::ZoneHandle(Z, result_.raw()); | 523 // instructions do not make a copy of the handle, so we do it. |
524 return Instance::ZoneHandle(Z, result_.raw()); | |
525 } | |
526 | |
527 Instance& StreamingConstantEvaluator::EvaluateListLiteral(intptr_t offset, | |
528 bool reset_position) { | |
529 bool got_cached = GetCachedConstant(offset, &result_); | |
530 if (!got_cached) { | |
531 intptr_t original_offset = builder_->ReaderOffset(); | |
532 builder_->SetOffset(offset); | |
533 builder_->ReadTag(); // skip tag. | |
534 EvaluateListLiteralInternal(); | |
535 | |
536 CacheConstantValue(offset, result_); | |
537 if (reset_position) builder_->SetOffset(original_offset); | |
538 } | |
539 // We return a new `ZoneHandle` here on purpose: The intermediate language | |
540 // instructions do not make a copy of the handle, so we do it. | |
541 return Instance::ZoneHandle(Z, result_.raw()); | |
542 } | |
543 | |
544 Instance& StreamingConstantEvaluator::EvaluateMapLiteral(intptr_t offset, | |
545 bool reset_position) { | |
546 bool got_cached = GetCachedConstant(offset, &result_); | |
547 if (!got_cached) { | |
548 intptr_t original_offset = builder_->ReaderOffset(); | |
549 builder_->SetOffset(offset); | |
550 builder_->ReadTag(); // skip tag. | |
551 EvaluateMapLiteralInternal(); | |
552 | |
553 CacheConstantValue(offset, result_); | |
554 if (reset_position) builder_->SetOffset(original_offset); | |
555 } | |
556 // We return a new `ZoneHandle` here on purpose: The intermediate language | |
557 // instructions do not make a copy of the handle, so we do it. | |
558 return Instance::ZoneHandle(Z, result_.raw()); | |
559 } | |
560 | |
561 Instance& StreamingConstantEvaluator::EvaluateConstructorInvocation( | |
562 intptr_t offset, | |
563 bool reset_position) { | |
564 bool got_cached = GetCachedConstant(offset, &result_); | |
565 if (!got_cached) { | |
566 intptr_t original_offset = builder_->ReaderOffset(); | |
567 builder_->SetOffset(offset); | |
568 builder_->ReadTag(); // skip tag. | |
569 EvaluateConstructorInvocationInternal(); | |
570 | |
571 CacheConstantValue(offset, result_); | |
572 if (reset_position) builder_->SetOffset(original_offset); | |
573 } | |
574 // We return a new `ZoneHandle` here on purpose: The intermediate language | |
575 // instructions do not make a copy of the handle, so we do it. | |
576 return Instance::ZoneHandle(Z, result_.raw()); | |
577 } | |
578 | |
579 Object& StreamingConstantEvaluator::EvaluateExpressionSafe(intptr_t offset) { | |
580 LongJumpScope jump; | |
581 if (setjmp(*jump.Set()) == 0) { | |
582 return EvaluateExpression(offset); | |
583 } else { | |
584 Thread* thread = H.thread(); | |
585 Error& error = Error::Handle(Z); | |
586 error = thread->sticky_error(); | |
587 thread->clear_sticky_error(); | |
588 return error; | |
589 } | |
590 } | |
591 | |
592 void StreamingConstantEvaluator::EvaluateVariableGet() { | |
593 // When we see a [VariableGet] the corresponding [VariableDeclaration] must've | |
594 // been executed already. It therefore must have a constant object associated | |
595 // with it. | |
596 builder_->ReadPosition(); // read position. | |
597 intptr_t variable_kernel_position = | |
598 builder_->ReadUInt(); // read kernel position. | |
599 builder_->ReadUInt(); // read relative variable index. | |
600 builder_->SkipOptionalDartType(); // read promoted type. | |
601 LocalVariable* variable = builder_->LookupVariable(variable_kernel_position); | |
602 ASSERT(variable->IsConst()); | |
603 result_ = variable->ConstValue()->raw(); | |
604 } | |
605 | |
606 void StreamingConstantEvaluator::EvaluateVariableGet(uint8_t payload) { | |
607 // When we see a [VariableGet] the corresponding [VariableDeclaration] must've | |
608 // been executed already. It therefore must have a constant object associated | |
609 // with it. | |
610 builder_->ReadPosition(); // read position. | |
611 intptr_t variable_kernel_position = | |
612 builder_->ReadUInt(); // read kernel position. | |
613 LocalVariable* variable = builder_->LookupVariable(variable_kernel_position); | |
614 ASSERT(variable->IsConst()); | |
615 result_ = variable->ConstValue()->raw(); | |
616 } | |
617 | |
618 void StreamingConstantEvaluator::EvaluatePropertyGet() { | |
619 builder_->ReadPosition(); // read position. | |
620 intptr_t expression_offset = builder_->ReaderOffset(); | |
621 builder_->SkipExpression(); // read receiver. | |
622 intptr_t name_string_index = builder_->ReadNameAsStringIndex(); // read name. | |
623 builder_->ReadUInt(); // Read unused "interface_target_reference". | |
624 | |
625 if (H.StringEquals(name_string_index, "length")) { | |
626 EvaluateExpression(expression_offset); | |
627 if (result_.IsString()) { | |
628 const dart::String& str = | |
629 dart::String::Handle(Z, dart::String::RawCast(result_.raw())); | |
630 result_ = Integer::New(str.Length()); | |
631 } else { | |
632 H.ReportError( | |
633 "Constant expressions can only call " | |
634 "'length' on string constants."); | |
635 } | |
636 } else { | |
637 UNREACHABLE(); | |
638 } | |
59 } | 639 } |
60 | 640 |
61 void StreamingConstantEvaluator::EvaluateStaticGet() { | 641 void StreamingConstantEvaluator::EvaluateStaticGet() { |
62 builder_->ReadPosition(); | 642 builder_->ReadPosition(); // read position. |
63 int canonical_name_index = builder_->ReadUInt(); | 643 intptr_t canonical_name_index = |
644 builder_->ReadUInt(); // read target_reference. | |
64 CanonicalName* target = builder_->GetCanonicalName(canonical_name_index); | 645 CanonicalName* target = builder_->GetCanonicalName(canonical_name_index); |
65 | 646 |
66 if (H.IsField(target)) { | 647 if (H.IsField(target)) { |
67 const dart::Field& field = | 648 const dart::Field& field = |
68 dart::Field::Handle(Z, H.LookupFieldByKernelField(target)); | 649 dart::Field::Handle(Z, H.LookupFieldByKernelField(target)); |
69 if (field.StaticValue() == Object::sentinel().raw() || | 650 if (field.StaticValue() == Object::sentinel().raw() || |
70 field.StaticValue() == Object::transition_sentinel().raw()) { | 651 field.StaticValue() == Object::transition_sentinel().raw()) { |
71 field.EvaluateInitializer(); | 652 field.EvaluateInitializer(); |
72 result_ = field.StaticValue(); | 653 result_ = field.StaticValue(); |
73 result_ = H.Canonicalize(result_); | 654 result_ = H.Canonicalize(result_); |
(...skipping 12 matching lines...) Expand all Loading... | |
86 result_ = closure_function.ImplicitStaticClosure(); | 667 result_ = closure_function.ImplicitStaticClosure(); |
87 result_ = H.Canonicalize(result_); | 668 result_ = H.Canonicalize(result_); |
88 } else if (H.IsGetter(target)) { | 669 } else if (H.IsGetter(target)) { |
89 UNIMPLEMENTED(); | 670 UNIMPLEMENTED(); |
90 } else { | 671 } else { |
91 UNIMPLEMENTED(); | 672 UNIMPLEMENTED(); |
92 } | 673 } |
93 } | 674 } |
94 } | 675 } |
95 | 676 |
677 void StreamingConstantEvaluator::EvaluateMethodInvocation() { | |
678 builder_->ReadPosition(); // read position. | |
679 // This method call wasn't cached, so receiver et al. isn't cached either. | |
680 const dart::Instance& receiver = | |
681 EvaluateExpression(builder_->ReaderOffset(), false); // read receiver. | |
682 dart::Class& klass = dart::Class::Handle( | |
683 Z, isolate_->class_table()->At(receiver.GetClassId())); | |
684 ASSERT(!klass.IsNull()); | |
685 | |
686 // Search the superclass chain for the selector. | |
687 dart::Function& function = dart::Function::Handle(Z); | |
688 const dart::String& method_name = | |
689 builder_->ReadNameAsMethodName(); // read name. | |
690 while (!klass.IsNull()) { | |
691 function = klass.LookupDynamicFunctionAllowPrivate(method_name); | |
692 if (!function.IsNull()) break; | |
693 klass = klass.SuperClass(); | |
694 } | |
695 | |
696 // The frontend should guarantee that [MethodInvocation]s inside constant | |
697 // expressions are always valid. | |
698 ASSERT(!function.IsNull()); | |
699 | |
700 // Read first parts of arguments: count and list of types. | |
701 intptr_t argument_count = builder_->PeekArgumentsCount(); | |
702 // Dart does not support generic methods yet. | |
703 ASSERT(builder_->PeekArgumentsTypeCount() == 0); | |
704 builder_->SkipArgumentsBeforeActualArguments(); | |
705 | |
706 // Run the method and canonicalize the result. | |
707 const Object& result = RunFunction(function, argument_count, &receiver, NULL); | |
708 result_ ^= result.raw(); | |
709 result_ = H.Canonicalize(result_); | |
710 | |
711 builder_->ReadUInt(); // read "interface_target_reference" | |
712 } | |
713 | |
714 void StreamingConstantEvaluator::EvaluateStaticInvocation() { | |
715 builder_->ReadPosition(); // read position. | |
716 CanonicalName* procedue_reference = builder_->GetCanonicalName( | |
717 builder_->ReadUInt()); // read procedure reference. | |
718 | |
719 const Function& function = Function::ZoneHandle( | |
720 Z, H.LookupStaticMethodByKernelProcedure(procedue_reference)); | |
721 dart::Class& klass = dart::Class::Handle(Z, function.Owner()); | |
722 | |
723 intptr_t argument_count = | |
724 builder_->ReadUInt(); // read arguments part #1: arguments count. | |
725 | |
726 // Build the type arguments vector (if necessary). | |
727 const TypeArguments* type_arguments = | |
728 TranslateTypeArguments(function, &klass); // read argument types. | |
729 | |
730 // read positional and named parameters. | |
731 const Object& result = | |
732 RunFunction(function, argument_count, NULL, type_arguments); | |
733 result_ ^= result.raw(); | |
734 result_ = H.Canonicalize(result_); | |
735 } | |
736 | |
737 void StreamingConstantEvaluator::EvaluateConstructorInvocationInternal() { | |
738 builder_->ReadPosition(); // read position. | |
739 | |
740 CanonicalName* target = | |
741 builder_->GetCanonicalName(builder_->ReadUInt()); // read target. | |
742 const Function& constructor = | |
743 Function::Handle(Z, H.LookupConstructorByKernelConstructor(target)); | |
744 dart::Class& klass = dart::Class::Handle(Z, constructor.Owner()); | |
745 | |
746 intptr_t argument_count = | |
747 builder_->ReadUInt(); // read arguments part #1: arguments count. | |
748 | |
749 // Build the type arguments vector (if necessary). | |
750 const TypeArguments* type_arguments = | |
751 TranslateTypeArguments(constructor, &klass); // read argument types. | |
752 | |
753 // Prepare either the instance or the type argument vector for the constructor | |
754 // call. | |
755 Instance* receiver = NULL; | |
756 const TypeArguments* type_arguments_argument = NULL; | |
757 if (!constructor.IsFactory()) { | |
758 receiver = &Instance::ZoneHandle(Z, Instance::New(klass, Heap::kOld)); | |
759 if (type_arguments != NULL) { | |
760 receiver->SetTypeArguments(*type_arguments); | |
761 } | |
762 } else { | |
763 type_arguments_argument = type_arguments; | |
764 } | |
765 | |
766 // read positional and named parameters. | |
767 const Object& result = RunFunction(constructor, argument_count, receiver, | |
768 type_arguments_argument); | |
769 | |
770 if (constructor.IsFactory()) { | |
771 // Factories return the new object. | |
772 result_ ^= result.raw(); | |
773 result_ = H.Canonicalize(result_); | |
774 } else { | |
775 ASSERT(!receiver->IsNull()); | |
776 result_ = H.Canonicalize(*receiver); | |
777 } | |
778 } | |
779 | |
780 void StreamingConstantEvaluator::EvaluateNot() { | |
781 result_ ^= Bool::Get(!EvaluateBooleanExpressionHere()).raw(); | |
782 } | |
783 | |
784 void StreamingConstantEvaluator::EvaluateLogicalExpression() { | |
785 bool left = EvaluateBooleanExpressionHere(); // read left. | |
786 LogicalOperator op = | |
787 static_cast<LogicalOperator>(builder_->ReadByte()); // read operator. | |
788 if (op == kAnd) { | |
789 if (left) { | |
790 EvaluateBooleanExpressionHere(); // read right. | |
791 } else { | |
792 builder_->SkipExpression(); // read right. | |
793 } | |
794 } else { | |
795 ASSERT(op == kOr); | |
796 if (!left) { | |
797 EvaluateBooleanExpressionHere(); // read right. | |
798 } else { | |
799 builder_->SkipExpression(); // read right. | |
800 } | |
801 } | |
802 } | |
803 | |
804 void StreamingConstantEvaluator::EvaluateConditionalExpression() { | |
805 bool condition = EvaluateBooleanExpressionHere(); | |
806 if (condition) { | |
807 EvaluateExpression(builder_->ReaderOffset(), false); // read then. | |
808 builder_->SkipExpression(); // read otherwise. | |
809 } else { | |
810 builder_->SkipExpression(); // read then. | |
811 EvaluateExpression(builder_->ReaderOffset(), false); // read otherwise. | |
812 } | |
813 builder_->SkipOptionalDartType(); // read unused static type. | |
814 } | |
815 | |
816 void StreamingConstantEvaluator::EvaluateStringConcatenation() { | |
817 builder_->ReadPosition(); // read position. | |
818 intptr_t length = builder_->ReadListLength(); // read list length. | |
819 | |
820 bool all_string = true; | |
821 const Array& strings = Array::Handle(Z, Array::New(length)); | |
822 for (intptr_t i = 0; i < length; ++i) { | |
823 EvaluateExpression(builder_->ReaderOffset(), false); | |
824 strings.SetAt(i, result_); | |
825 all_string = all_string && result_.IsString(); | |
826 } | |
827 if (all_string) { | |
828 result_ = dart::String::ConcatAll(strings, Heap::kOld); | |
829 result_ = H.Canonicalize(result_); | |
830 } else { | |
831 // Get string interpolation function. | |
832 const dart::Class& cls = dart::Class::Handle( | |
833 Z, dart::Library::LookupCoreClass(Symbols::StringBase())); | |
834 ASSERT(!cls.IsNull()); | |
835 const Function& func = Function::Handle( | |
836 Z, cls.LookupStaticFunction( | |
837 dart::Library::PrivateCoreLibName(Symbols::Interpolate()))); | |
838 ASSERT(!func.IsNull()); | |
839 | |
840 // Build argument array to pass to the interpolation function. | |
841 const Array& interpolate_arg = Array::Handle(Z, Array::New(1, Heap::kOld)); | |
842 interpolate_arg.SetAt(0, strings); | |
843 | |
844 // Run and canonicalize. | |
845 const Object& result = | |
846 RunFunction(func, interpolate_arg, Array::null_array()); | |
847 result_ = H.Canonicalize(dart::String::Cast(result)); | |
848 } | |
849 } | |
96 | 850 |
97 void StreamingConstantEvaluator::EvaluateSymbolLiteral() { | 851 void StreamingConstantEvaluator::EvaluateSymbolLiteral() { |
98 int str_index = builder_->ReadUInt(); | 852 intptr_t str_index = builder_->ReadUInt(); // read index into string table. |
99 const dart::String& symbol_value = H.DartSymbol(str_index); | 853 const dart::String& symbol_value = H.DartSymbol(str_index); |
100 | 854 |
101 const dart::Class& symbol_class = | 855 const dart::Class& symbol_class = |
102 dart::Class::ZoneHandle(Z, I->object_store()->symbol_class()); | 856 dart::Class::ZoneHandle(Z, I->object_store()->symbol_class()); |
103 ASSERT(!symbol_class.IsNull()); | 857 ASSERT(!symbol_class.IsNull()); |
104 const dart::Function& symbol_constructor = Function::ZoneHandle( | 858 const dart::Function& symbol_constructor = Function::ZoneHandle( |
105 Z, symbol_class.LookupConstructor(Symbols::SymbolCtor())); | 859 Z, symbol_class.LookupConstructor(Symbols::SymbolCtor())); |
106 ASSERT(!symbol_constructor.IsNull()); | 860 ASSERT(!symbol_constructor.IsNull()); |
107 result_ ^= EvaluateConstConstructorCall( | 861 result_ ^= EvaluateConstConstructorCall( |
108 symbol_class, TypeArguments::Handle(Z), symbol_constructor, symbol_value); | 862 symbol_class, TypeArguments::Handle(Z), symbol_constructor, symbol_value); |
109 } | 863 } |
110 | 864 |
865 void StreamingConstantEvaluator::EvaluateTypeLiteral() { | |
866 const AbstractType& type = T.BuildType(); | |
867 if (type.IsMalformed()) { | |
868 H.ReportError("Malformed type literal in constant expression."); | |
869 } | |
870 result_ = type.raw(); | |
871 } | |
872 | |
873 void StreamingConstantEvaluator::EvaluateListLiteralInternal() { | |
874 builder_->ReadPosition(); // read position. | |
875 const TypeArguments& type_arguments = T.BuildTypeArguments(1); // read type. | |
876 intptr_t length = builder_->ReadListLength(); // read list length. | |
877 const Array& const_list = | |
878 Array::ZoneHandle(Z, Array::New(length, Heap::kOld)); | |
879 const_list.SetTypeArguments(type_arguments); | |
880 for (intptr_t i = 0; i < length; ++i) { | |
881 const Instance& expression = EvaluateExpression( | |
882 builder_->ReaderOffset(), false); // read ith expression. | |
883 const_list.SetAt(i, expression); | |
884 } | |
885 const_list.MakeImmutable(); | |
886 result_ = H.Canonicalize(const_list); | |
887 } | |
888 | |
889 void StreamingConstantEvaluator::EvaluateMapLiteralInternal() { | |
890 builder_->ReadPosition(); // read position. | |
891 const TypeArguments& type_arguments = T.BuildTypeArguments(2); | |
892 | |
893 intptr_t length = builder_->ReadListLength(); // read length of entries. | |
894 | |
895 // This wasn't cached, so content isn't cached either. | |
896 Array& const_kv_array = | |
897 Array::ZoneHandle(Z, Array::New(2 * length, Heap::kOld)); | |
898 for (intptr_t i = 0; i < length; ++i) { | |
899 const_kv_array.SetAt(2 * i + 0, EvaluateExpression(builder_->ReaderOffset(), | |
900 false)); // read key. | |
901 const_kv_array.SetAt(2 * i + 1, EvaluateExpression(builder_->ReaderOffset(), | |
902 false)); // read value. | |
903 } | |
904 | |
905 const_kv_array.MakeImmutable(); | |
906 const_kv_array ^= H.Canonicalize(const_kv_array); | |
907 | |
908 const dart::Class& map_class = dart::Class::Handle( | |
909 Z, dart::Library::LookupCoreClass(Symbols::ImmutableMap())); | |
910 ASSERT(!map_class.IsNull()); | |
911 ASSERT(map_class.NumTypeArguments() == 2); | |
912 | |
913 const dart::Field& field = dart::Field::Handle( | |
914 Z, map_class.LookupInstanceFieldAllowPrivate(H.DartSymbol("_kvPairs"))); | |
915 ASSERT(!field.IsNull()); | |
916 | |
917 // NOTE: This needs to be kept in sync with `runtime/lib/immutable_map.dart`! | |
918 result_ = Instance::New(map_class, Heap::kOld); | |
919 ASSERT(!result_.IsNull()); | |
920 result_.SetTypeArguments(type_arguments); | |
921 result_.SetField(field, const_kv_array); | |
922 result_ = H.Canonicalize(result_); | |
923 } | |
924 | |
925 void StreamingConstantEvaluator::EvaluateLet() { | |
926 intptr_t kernel_position = builder_->ReaderOffset(); | |
927 LocalVariable* local = builder_->LookupVariable(kernel_position); | |
928 | |
929 // read variable declaration. | |
930 builder_->ReadPosition(); // read position. | |
931 builder_->ReadPosition(); // read equals position. | |
932 builder_->ReadFlags(); // read flags. | |
933 builder_->ReadUInt(); // read name index. | |
934 builder_->SkipDartType(); // read type. | |
935 Tag tag = builder_->ReadTag(); // read (first part of) initializer. | |
936 if (tag == kNothing) { | |
937 local->SetConstValue(Instance::ZoneHandle(Z, dart::Instance::null())); | |
938 } else { | |
939 local->SetConstValue(EvaluateExpression(builder_->ReaderOffset(), false)); | |
940 } | |
941 | |
942 // read body | |
943 EvaluateExpression(builder_->ReaderOffset(), false); | |
944 } | |
945 | |
946 void StreamingConstantEvaluator::EvaluateBigIntLiteral() { | |
947 const dart::String& value = | |
948 H.DartString(builder_->ReadUInt()); // read string reference. | |
949 result_ = Integer::New(value, Heap::kOld); | |
950 result_ = H.Canonicalize(result_); | |
951 } | |
952 | |
953 void StreamingConstantEvaluator::EvaluateStringLiteral() { | |
954 intptr_t str_index = builder_->ReadUInt(); // read string reference. | |
955 result_ = H.DartSymbol(str_index).raw(); | |
956 } | |
957 | |
958 void StreamingConstantEvaluator::EvaluateIntLiteral(uint8_t payload) { | |
959 int64_t value = static_cast<int32_t>(payload) - SpecializedIntLiteralBias; | |
960 result_ = dart::Integer::New(value, Heap::kOld); | |
961 result_ = H.Canonicalize(result_); | |
962 } | |
963 | |
964 void StreamingConstantEvaluator::EvaluateIntLiteral(bool is_negative) { | |
965 int64_t value = is_negative ? -static_cast<int64_t>(builder_->ReadUInt()) | |
966 : builder_->ReadUInt(); // read value. | |
967 result_ = dart::Integer::New(value, Heap::kOld); | |
968 result_ = H.Canonicalize(result_); | |
969 } | |
111 | 970 |
112 void StreamingConstantEvaluator::EvaluateDoubleLiteral() { | 971 void StreamingConstantEvaluator::EvaluateDoubleLiteral() { |
113 int str_index = builder_->ReadUInt(); | 972 intptr_t str_index = builder_->ReadUInt(); // read index into string table. |
114 result_ = dart::Double::New(H.DartString(str_index), Heap::kOld); | 973 result_ = Double::New(H.DartString(str_index), Heap::kOld); |
115 result_ = H.Canonicalize(result_); | 974 result_ = H.Canonicalize(result_); |
116 } | 975 } |
117 | 976 |
977 void StreamingConstantEvaluator::EvaluateBoolLiteral(bool value) { | |
978 result_ = dart::Bool::Get(value).raw(); | |
979 } | |
980 | |
981 void StreamingConstantEvaluator::EvaluateNullLiteral() { | |
982 result_ = dart::Instance::null(); | |
983 } | |
984 | |
985 // This depends on being about to read the list of positionals on arguments. | |
986 const Object& StreamingConstantEvaluator::RunFunction( | |
987 const Function& function, | |
988 intptr_t argument_count, | |
989 const Instance* receiver, | |
990 const TypeArguments* type_args) { | |
991 // We do not support generic methods yet. | |
992 ASSERT((receiver == NULL) || (type_args == NULL)); | |
993 intptr_t extra_arguments = | |
994 (receiver != NULL ? 1 : 0) + (type_args != NULL ? 1 : 0); | |
995 | |
996 // Build up arguments. | |
997 const Array& arguments = | |
998 Array::ZoneHandle(Z, Array::New(extra_arguments + argument_count)); | |
999 intptr_t pos = 0; | |
1000 if (receiver != NULL) { | |
1001 arguments.SetAt(pos++, *receiver); | |
1002 } | |
1003 if (type_args != NULL) { | |
1004 arguments.SetAt(pos++, *type_args); | |
1005 } | |
1006 | |
1007 // List of positional. | |
1008 intptr_t list_length = builder_->ReadListLength(); // read list length. | |
1009 for (intptr_t i = 0; i < list_length; ++i) { | |
1010 EvaluateExpression(builder_->ReaderOffset(), | |
1011 false); // read ith expression. | |
1012 arguments.SetAt(pos++, result_); | |
1013 } | |
1014 | |
1015 // List of named. | |
1016 list_length = builder_->ReadListLength(); // read list length. | |
1017 const Array& names = Array::ZoneHandle(Z, Array::New(list_length)); | |
1018 for (intptr_t i = 0; i < list_length; ++i) { | |
1019 dart::String& name = | |
1020 H.DartSymbol(builder_->ReadUInt()); // read ith name index. | |
1021 names.SetAt(i, name); | |
1022 EvaluateExpression(builder_->ReaderOffset(), | |
1023 false); // read ith expression. | |
1024 arguments.SetAt(pos++, result_); | |
1025 } | |
1026 | |
1027 return RunFunction(function, arguments, names); | |
1028 } | |
1029 | |
1030 const Object& StreamingConstantEvaluator::RunFunction(const Function& function, | |
1031 const Array& arguments, | |
1032 const Array& names) { | |
1033 const Array& args_descriptor = | |
1034 Array::Handle(Z, ArgumentsDescriptor::New(arguments.Length(), names)); | |
1035 const Object& result = Object::Handle( | |
1036 Z, DartEntry::InvokeFunction(function, arguments, args_descriptor)); | |
1037 if (result.IsError()) { | |
1038 H.ReportError(Error::Cast(result), "error evaluating constant constructor"); | |
1039 } | |
1040 return result; | |
1041 } | |
118 | 1042 |
119 RawObject* StreamingConstantEvaluator::EvaluateConstConstructorCall( | 1043 RawObject* StreamingConstantEvaluator::EvaluateConstConstructorCall( |
120 const dart::Class& type_class, | 1044 const dart::Class& type_class, |
121 const TypeArguments& type_arguments, | 1045 const TypeArguments& type_arguments, |
122 const Function& constructor, | 1046 const Function& constructor, |
123 const Object& argument) { | 1047 const Object& argument) { |
124 // Factories have one extra argument: the type arguments. | 1048 // Factories have one extra argument: the type arguments. |
125 // Constructors have 1 extra arguments: receiver. | 1049 // Constructors have 1 extra arguments: receiver. |
126 const int kNumArgs = 1; | 1050 const int kNumArgs = 1; |
127 const int kNumExtraArgs = 1; | 1051 const int kNumExtraArgs = 1; |
(...skipping 20 matching lines...) Expand all Loading... | |
148 const Object& result = Object::Handle( | 1072 const Object& result = Object::Handle( |
149 Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor)); | 1073 Z, DartEntry::InvokeFunction(constructor, arg_values, args_descriptor)); |
150 ASSERT(!result.IsError()); | 1074 ASSERT(!result.IsError()); |
151 if (constructor.IsFactory()) { | 1075 if (constructor.IsFactory()) { |
152 // The factory method returns the allocated object. | 1076 // The factory method returns the allocated object. |
153 instance ^= result.raw(); | 1077 instance ^= result.raw(); |
154 } | 1078 } |
155 return H.Canonicalize(instance); | 1079 return H.Canonicalize(instance); |
156 } | 1080 } |
157 | 1081 |
1082 const TypeArguments* StreamingConstantEvaluator::TranslateTypeArguments( | |
1083 const Function& target, | |
1084 dart::Class* target_klass) { | |
1085 intptr_t types_count = builder_->ReadListLength(); // read types count. | |
1086 | |
1087 const TypeArguments* type_arguments = NULL; | |
1088 if (types_count > 0) { | |
1089 type_arguments = &T.BuildInstantiatedTypeArguments( | |
1090 *target_klass, types_count); // read types. | |
1091 | |
1092 if (!(type_arguments->IsNull() || type_arguments->IsInstantiated())) { | |
1093 H.ReportError("Type must be constant in const constructor."); | |
1094 } | |
1095 } else if (target.IsFactory() && type_arguments == NULL) { | |
1096 // All factories take a type arguments vector as first argument (independent | |
1097 // of whether the class is generic or not). | |
1098 type_arguments = &TypeArguments::ZoneHandle(Z, TypeArguments::null()); | |
1099 } | |
1100 return type_arguments; | |
1101 } | |
1102 | |
1103 bool StreamingConstantEvaluator::EvaluateBooleanExpressionHere() { | |
1104 EvaluateExpression(builder_->ReaderOffset(), false); | |
1105 AssertBoolInCheckedMode(); | |
1106 return result_.raw() == Bool::True().raw(); | |
1107 } | |
1108 | |
158 bool StreamingConstantEvaluator::GetCachedConstant(intptr_t kernel_offset, | 1109 bool StreamingConstantEvaluator::GetCachedConstant(intptr_t kernel_offset, |
159 Instance* value) { | 1110 Instance* value) { |
160 if (builder_ == NULL) return false; | 1111 if (builder_ == NULL) return false; |
161 | 1112 |
162 const Function& function = builder_->parsed_function()->function(); | 1113 const Function& function = builder_->parsed_function()->function(); |
163 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { | 1114 if (function.kind() == RawFunction::kImplicitStaticFinalGetter) { |
164 // Don't cache constants in initializer expressions. They get | 1115 // Don't cache constants in initializer expressions. They get |
165 // evaluated only once. | 1116 // evaluated only once. |
166 return false; | 1117 return false; |
167 } | 1118 } |
168 | 1119 |
169 bool is_present = false; | 1120 bool is_present = false; |
170 ASSERT(!script_.InVMHeap()); | 1121 ASSERT(!script_.InVMHeap()); |
171 if (script_.compile_time_constants() == Array::null()) { | 1122 if (script_.compile_time_constants() == Array::null()) { |
172 return false; | 1123 return false; |
173 } | 1124 } |
174 KernelConstantsMap constants(script_.compile_time_constants()); | 1125 KernelConstantsMap constants(script_.compile_time_constants()); |
175 *value ^= constants.GetOrNull(kernel_offset, &is_present); | 1126 *value ^= constants.GetOrNull(kernel_offset, &is_present); |
176 // Mutator compiler thread may add constants while background compiler | 1127 // Mutator compiler thread may add constants while background compiler |
177 // is running, and thus change the value of 'compile_time_constants'; | 1128 // is running, and thus change the value of 'compile_time_constants'; |
178 // do not assert that 'compile_time_constants' has not changed. | 1129 // do not assert that 'compile_time_constants' has not changed. |
179 constants.Release(); | 1130 constants.Release(); |
180 if (FLAG_compiler_stats && is_present) { | 1131 if (FLAG_compiler_stats && is_present) { |
181 H.thread()->compiler_stats()->num_const_cache_hits++; | 1132 ++H.thread()->compiler_stats()->num_const_cache_hits; |
182 } | 1133 } |
183 return is_present; | 1134 return is_present; |
184 } | 1135 } |
185 | 1136 |
186 | 1137 |
187 void StreamingConstantEvaluator::CacheConstantValue(intptr_t kernel_offset, | 1138 void StreamingConstantEvaluator::CacheConstantValue(intptr_t kernel_offset, |
188 const Instance& value) { | 1139 const Instance& value) { |
189 ASSERT(Thread::Current()->IsMutatorThread()); | 1140 ASSERT(Thread::Current()->IsMutatorThread()); |
190 | 1141 |
191 if (builder_ == NULL) return; | 1142 if (builder_ == NULL) return; |
(...skipping 10 matching lines...) Expand all Loading... | |
202 const Array& array = Array::Handle( | 1153 const Array& array = Array::Handle( |
203 HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew)); | 1154 HashTables::New<KernelConstantsMap>(kInitialConstMapSize, Heap::kNew)); |
204 script_.set_compile_time_constants(array); | 1155 script_.set_compile_time_constants(array); |
205 } | 1156 } |
206 KernelConstantsMap constants(script_.compile_time_constants()); | 1157 KernelConstantsMap constants(script_.compile_time_constants()); |
207 constants.InsertNewOrGetValue(kernel_offset, value); | 1158 constants.InsertNewOrGetValue(kernel_offset, value); |
208 script_.set_compile_time_constants(constants.Release()); | 1159 script_.set_compile_time_constants(constants.Release()); |
209 } | 1160 } |
210 | 1161 |
211 | 1162 |
212 Fragment StreamingFlowGraphBuilder::BuildAt(intptr_t kernel_offset) { | 1163 Fragment StreamingFlowGraphBuilder::BuildExpressionAt(intptr_t kernel_offset) { |
213 SetOffset(kernel_offset); | 1164 SetOffset(kernel_offset); |
1165 return BuildExpression(); // read expression. | |
1166 } | |
214 | 1167 |
1168 Fragment StreamingFlowGraphBuilder::BuildExpression() { | |
215 uint8_t payload = 0; | 1169 uint8_t payload = 0; |
216 Tag tag = ReadTag(&payload); | 1170 Tag tag = ReadTag(&payload); // read tag. |
217 switch (tag) { | 1171 switch (tag) { |
218 case kInvalidExpression: | 1172 case kInvalidExpression: |
219 return BuildInvalidExpression(); | 1173 return BuildInvalidExpression(); |
220 // case kVariableGet: | 1174 case kVariableGet: |
221 // return VariableGet::ReadFrom(reader_); | 1175 return BuildVariableGet(); |
222 // case kSpecializedVariableGet: | 1176 case kSpecializedVariableGet: |
223 // return VariableGet::ReadFrom(reader_, payload); | 1177 return BuildVariableGet(payload); |
224 // case kVariableSet: | 1178 case kVariableSet: |
225 // return VariableSet::ReadFrom(reader_); | 1179 return BuildVariableSet(); |
226 // case kSpecializedVariableSet: | 1180 case kSpecializedVariableSet: |
227 // return VariableSet::ReadFrom(reader_, payload); | 1181 return BuildVariableSet(payload); |
228 // case kPropertyGet: | 1182 case kPropertyGet: |
229 // return PropertyGet::ReadFrom(reader_); | 1183 return BuildPropertyGet(); |
230 // case kPropertySet: | 1184 case kPropertySet: |
231 // return PropertySet::ReadFrom(reader_); | 1185 return BuildPropertySet(); |
232 // case kDirectPropertyGet: | 1186 case kDirectPropertyGet: |
233 // return DirectPropertyGet::ReadFrom(reader_); | 1187 return BuildDirectPropertyGet(); |
234 // case kDirectPropertySet: | 1188 case kDirectPropertySet: |
235 // return DirectPropertySet::ReadFrom(reader_); | 1189 return BuildDirectPropertySet(); |
236 case kStaticGet: | 1190 case kStaticGet: |
237 return BuildStaticGet(); | 1191 return BuildStaticGet(); |
238 // case kStaticSet: | 1192 case kStaticSet: |
239 // return StaticSet::ReadFrom(reader_); | 1193 return BuildStaticSet(); |
240 // case kMethodInvocation: | 1194 case kMethodInvocation: |
241 // return MethodInvocation::ReadFrom(reader_); | 1195 return BuildMethodInvocation(); |
242 // case kDirectMethodInvocation: | 1196 case kDirectMethodInvocation: |
243 // return DirectMethodInvocation::ReadFrom(reader_); | 1197 return BuildDirectMethodInvocation(); |
244 // case kStaticInvocation: | 1198 case kStaticInvocation: |
245 // return StaticInvocation::ReadFrom(reader_, false); | 1199 return BuildStaticInvocation(false); |
246 // case kConstStaticInvocation: | 1200 case kConstStaticInvocation: |
247 // return StaticInvocation::ReadFrom(reader_, true); | 1201 return BuildStaticInvocation(true); |
248 // case kConstructorInvocation: | 1202 case kConstructorInvocation: |
249 // return ConstructorInvocation::ReadFrom(reader_, false); | 1203 return BuildConstructorInvocation(false); |
250 // case kConstConstructorInvocation: | 1204 case kConstConstructorInvocation: |
251 // return ConstructorInvocation::ReadFrom(reader_, true); | 1205 return BuildConstructorInvocation(true); |
252 // case kNot: | 1206 case kNot: |
253 // return Not::ReadFrom(reader_); | 1207 return BuildNot(); |
254 // case kLogicalExpression: | 1208 case kLogicalExpression: |
255 // return LogicalExpression::ReadFrom(reader_); | 1209 return BuildLogicalExpression(); |
256 // case kConditionalExpression: | 1210 case kConditionalExpression: |
257 // return ConditionalExpression::ReadFrom(reader_); | 1211 return BuildConditionalExpression(); |
258 // case kStringConcatenation: | 1212 case kStringConcatenation: |
259 // return StringConcatenation::ReadFrom(reader_); | 1213 return BuildStringConcatenation(); |
260 // case kIsExpression: | 1214 case kIsExpression: |
261 // return IsExpression::ReadFrom(reader_); | 1215 return BuildIsExpression(); |
262 // case kAsExpression: | 1216 case kAsExpression: |
263 // return AsExpression::ReadFrom(reader_); | 1217 return BuildAsExpression(); |
264 case kSymbolLiteral: | 1218 case kSymbolLiteral: |
265 return BuildSymbolLiteral(); | 1219 return BuildSymbolLiteral(); |
266 // case kTypeLiteral: | 1220 case kTypeLiteral: |
267 // return TypeLiteral::ReadFrom(reader_); | 1221 return BuildTypeLiteral(); |
268 case kThisExpression: | 1222 case kThisExpression: |
269 return BuildThisExpression(); | 1223 return BuildThisExpression(); |
270 case kRethrow: | 1224 case kRethrow: |
271 return BuildRethrow(); | 1225 return BuildRethrow(); |
272 // case kThrow: | 1226 case kThrow: |
273 // return Throw::ReadFrom(reader_); | 1227 return BuildThrow(); |
274 // case kListLiteral: | 1228 case kListLiteral: |
275 // return ListLiteral::ReadFrom(reader_, false); | 1229 return BuildListLiteral(false); |
276 // case kConstListLiteral: | 1230 case kConstListLiteral: |
277 // return ListLiteral::ReadFrom(reader_, true); | 1231 return BuildListLiteral(true); |
278 // case kMapLiteral: | 1232 case kMapLiteral: |
279 // return MapLiteral::ReadFrom(reader_, false); | 1233 return BuildMapLiteral(false); |
280 // case kConstMapLiteral: | 1234 case kConstMapLiteral: |
281 // return MapLiteral::ReadFrom(reader_, true); | 1235 return BuildMapLiteral(true); |
282 // case kAwaitExpression: | 1236 case kFunctionExpression: |
283 // return AwaitExpression::ReadFrom(reader_); | 1237 // TODO(jensj) |
284 // case kFunctionExpression: | 1238 UNIMPLEMENTED(); |
285 // return FunctionExpression::ReadFrom(reader_); | 1239 return Fragment(); |
286 // case kLet: | 1240 case kLet: |
287 // return Let::ReadFrom(reader_); | 1241 return BuildLet(); |
288 case kBigIntLiteral: | 1242 case kBigIntLiteral: |
289 return BuildBigIntLiteral(); | 1243 return BuildBigIntLiteral(); |
290 case kStringLiteral: | 1244 case kStringLiteral: |
291 return BuildStringLiteral(); | 1245 return BuildStringLiteral(); |
292 case kSpecialIntLiteral: | 1246 case kSpecialIntLiteral: |
293 return BuildIntLiteral(payload); | 1247 return BuildIntLiteral(payload); |
294 case kNegativeIntLiteral: | 1248 case kNegativeIntLiteral: |
295 return BuildIntLiteral(true); | 1249 return BuildIntLiteral(true); |
296 case kPositiveIntLiteral: | 1250 case kPositiveIntLiteral: |
297 return BuildIntLiteral(false); | 1251 return BuildIntLiteral(false); |
298 case kDoubleLiteral: | 1252 case kDoubleLiteral: |
299 return BuildDoubleLiteral(); | 1253 return BuildDoubleLiteral(); |
300 case kTrueLiteral: | 1254 case kTrueLiteral: |
301 return BuildBoolLiteral(true); | 1255 return BuildBoolLiteral(true); |
302 case kFalseLiteral: | 1256 case kFalseLiteral: |
303 return BuildBoolLiteral(false); | 1257 return BuildBoolLiteral(false); |
304 case kNullLiteral: | 1258 case kNullLiteral: |
305 return BuildNullLiteral(); | 1259 return BuildNullLiteral(); |
306 default: | 1260 default: |
307 UNREACHABLE(); | 1261 UNREACHABLE(); |
308 } | 1262 } |
309 | 1263 |
310 return Fragment(); | 1264 return Fragment(); |
311 } | 1265 } |
312 | 1266 |
1267 Fragment StreamingFlowGraphBuilder::BuildStatementAt(intptr_t kernel_offset) { | |
1268 SetOffset(kernel_offset); | |
1269 return BuildStatement(); // read statement. | |
1270 } | |
1271 | |
1272 Fragment StreamingFlowGraphBuilder::BuildStatement() { | |
1273 Tag tag = ReadTag(); // read tag. | |
1274 switch (tag) { | |
1275 case kInvalidStatement: | |
1276 return BuildInvalidStatement(); | |
1277 case kExpressionStatement: | |
1278 return BuildExpressionStatement(); | |
1279 case kBlock: | |
1280 return BuildBlock(); | |
1281 case kEmptyStatement: | |
1282 return BuildEmptyStatement(); | |
1283 case kAssertStatement: | |
1284 return BuildAssertStatement(); | |
1285 case kLabeledStatement: | |
1286 return BuildLabeledStatement(); | |
1287 case kBreakStatement: | |
1288 return BuildBreakStatement(); | |
1289 case kWhileStatement: | |
1290 return BuildWhileStatement(); | |
1291 case kDoStatement: | |
1292 return BuildDoStatement(); | |
1293 case kForStatement: | |
1294 return BuildForStatement(); | |
1295 case kForInStatement: | |
1296 return BuildForInStatement(false); | |
1297 case kAsyncForInStatement: | |
1298 return BuildForInStatement(true); | |
1299 case kSwitchStatement: | |
1300 return BuildSwitchStatement(); | |
1301 case kContinueSwitchStatement: | |
1302 return BuildContinueSwitchStatement(); | |
1303 case kIfStatement: | |
1304 return BuildIfStatement(); | |
1305 case kReturnStatement: | |
1306 return BuildReturnStatement(); | |
1307 case kTryCatch: | |
1308 return BuildTryCatch(); | |
1309 case kTryFinally: | |
1310 return BuildTryFinally(); | |
1311 case kYieldStatement: | |
1312 return BuildYieldStatement(); | |
1313 case kVariableDeclaration: | |
1314 return BuildVariableDeclaration(true); | |
1315 case kFunctionDeclaration: | |
1316 // TODO(jensj) | |
1317 UNIMPLEMENTED(); | |
1318 return Fragment(); | |
1319 default: | |
1320 UNREACHABLE(); | |
1321 } | |
1322 return Fragment(); | |
1323 } | |
1324 | |
1325 void StreamingFlowGraphBuilder::SkipStatement() { | |
1326 Tag tag = ReadTag(); // read tag. | |
1327 switch (tag) { | |
1328 case kInvalidStatement: | |
1329 return; | |
1330 case kExpressionStatement: | |
1331 SkipExpression(); // read expression. | |
1332 return; | |
1333 case kBlock: { | |
1334 intptr_t list_length = ReadListLength(); // read number of statements. | |
1335 for (intptr_t i = 0; i < list_length; ++i) { | |
1336 SkipStatement(); // read ith statement. | |
1337 } | |
1338 return; | |
1339 } | |
1340 case kEmptyStatement: | |
1341 return; | |
1342 case kAssertStatement: { | |
1343 SkipExpression(); // Read condition. | |
1344 Tag tag = ReadTag(); // read (first part of) message. | |
1345 if (tag == kSomething) { | |
1346 SkipExpression(); // read (rest of) message. | |
1347 } | |
1348 return; | |
1349 } | |
1350 case kLabeledStatement: | |
1351 SkipStatement(); // read body. | |
1352 return; | |
1353 case kBreakStatement: | |
1354 ReadPosition(); // read position. | |
1355 ReadUInt(); // read target_index. | |
1356 return; | |
1357 case kWhileStatement: | |
1358 SkipExpression(); // read condition. | |
1359 SkipStatement(); // read body. | |
1360 return; | |
1361 case kDoStatement: | |
1362 SkipStatement(); // read body. | |
1363 SkipExpression(); // read condition. | |
1364 return; | |
1365 case kForStatement: { | |
1366 intptr_t list_length = ReadListLength(); // read number of variables. | |
1367 for (intptr_t i = 0; i < list_length; ++i) { | |
1368 SkipVariableDeclaration(); // read ith variable. | |
1369 } | |
1370 Tag tag = ReadTag(); // Read first part of condition. | |
1371 if (tag == kSomething) { | |
1372 SkipExpression(); // read rest of condition. | |
1373 } | |
1374 list_length = ReadListLength(); // read number of updates. | |
1375 for (intptr_t i = 0; i < list_length; ++i) { | |
1376 SkipExpression(); // read ith update. | |
1377 } | |
1378 SkipStatement(); // read body. | |
1379 return; | |
1380 } | |
1381 case kForInStatement: | |
1382 case kAsyncForInStatement: | |
1383 ReadPosition(); // read position. | |
1384 SkipVariableDeclaration(); // read variable. | |
1385 SkipExpression(); // read iterable. | |
1386 SkipStatement(); // read body. | |
1387 return; | |
1388 case kSwitchStatement: { | |
1389 SkipExpression(); // read condition. | |
1390 int num_cases = ReadListLength(); // read number of cases. | |
1391 for (intptr_t i = 0; i < num_cases; ++i) { | |
1392 int num_expressions = ReadListLength(); // read number of expressions. | |
1393 for (intptr_t j = 0; j < num_expressions; ++j) { | |
1394 ReadPosition(); // read jth position. | |
1395 SkipExpression(); // read jth expression. | |
1396 } | |
1397 ReadBool(); // read is_default. | |
1398 SkipStatement(); // read body. | |
1399 } | |
1400 return; | |
1401 } | |
1402 case kContinueSwitchStatement: | |
1403 ReadUInt(); // read target_index. | |
1404 return; | |
1405 case kIfStatement: | |
1406 SkipExpression(); // read condition. | |
1407 SkipStatement(); // read then. | |
1408 SkipStatement(); // read otherwise. | |
1409 return; | |
1410 case kReturnStatement: { | |
1411 ReadPosition(); // read position | |
1412 Tag tag = ReadTag(); // read (first part of) expression. | |
1413 if (tag == kSomething) { | |
1414 SkipExpression(); // read (rest of) expression. | |
1415 } | |
1416 return; | |
1417 } | |
1418 case kTryCatch: { | |
1419 SkipStatement(); // read body. | |
1420 ReadBool(); // read any_catch_needs_stack_trace. | |
1421 intptr_t num_matches = ReadListLength(); // read number of catches. | |
1422 for (intptr_t i = 0; i < num_matches; ++i) { | |
1423 SkipDartType(); // read guard. | |
1424 tag = ReadTag(); // read first part of exception. | |
1425 if (tag == kSomething) { | |
1426 SkipVariableDeclaration(); // read exception. | |
1427 } | |
1428 tag = ReadTag(); // read first part of stack trace. | |
1429 if (tag == kSomething) { | |
1430 SkipVariableDeclaration(); // read stack trace. | |
1431 } | |
1432 SkipStatement(); // read body. | |
1433 } | |
1434 return; | |
1435 } | |
1436 case kTryFinally: | |
1437 SkipStatement(); // read body. | |
1438 SkipStatement(); // read finalizer. | |
1439 return; | |
1440 case kYieldStatement: | |
1441 ReadPosition(); // read position. | |
1442 ReadByte(); // read flags. | |
1443 SkipExpression(); // read expression. | |
1444 return; | |
1445 case kVariableDeclaration: | |
1446 SkipVariableDeclaration(); | |
1447 return; | |
1448 case kFunctionDeclaration: | |
1449 // TODO(jensj) | |
1450 UNIMPLEMENTED(); | |
1451 return; | |
1452 default: | |
1453 UNREACHABLE(); | |
1454 } | |
1455 } | |
313 | 1456 |
314 CanonicalName* StreamingFlowGraphBuilder::GetCanonicalName(intptr_t index) { | 1457 CanonicalName* StreamingFlowGraphBuilder::GetCanonicalName(intptr_t index) { |
315 if (index == 0) return NULL; | 1458 if (index == 0) return NULL; |
316 --index; | 1459 --index; |
317 | 1460 |
318 if (canonical_names_ != NULL && canonical_names_entries_read_ > index) { | 1461 if (canonical_names_ != NULL && canonical_names_entries_read_ > index) { |
319 return canonical_names_[index]; | 1462 return canonical_names_[index]; |
320 } | 1463 } |
321 | 1464 |
322 intptr_t saved_offset = ReaderOffset(); | 1465 intptr_t saved_offset = ReaderOffset(); |
323 if (canonical_names_ == NULL) { | 1466 if (canonical_names_ == NULL) { |
324 // Find offset from where to read canonical names table. | 1467 // Find offset from where to read canonical names table. |
325 | 1468 |
326 // Skip the magic number. | 1469 // Skip the magic number. |
327 reader_->set_offset(4); | 1470 reader_->set_offset(4); |
328 | 1471 |
329 // Skip the string table. The last offset is the end offset of the last | 1472 // Skip the string table. The last offset is the end offset of the last |
330 // string which gives the length of the string data. | 1473 // string which gives the length of the string data. |
331 intptr_t list_length = ReadListLength(); | 1474 intptr_t list_length = ReadListLength(); // read list length. |
332 intptr_t end_offset = 0; | 1475 intptr_t end_offset = 0; |
333 for (intptr_t i = 0; i < list_length; ++i) { | 1476 for (intptr_t i = 0; i < list_length; ++i) { |
334 end_offset = ReadUInt(); | 1477 end_offset = ReadUInt(); // read ith offset. |
335 } | 1478 } |
336 SkipBytes(end_offset); | 1479 SkipBytes(end_offset); |
337 | 1480 |
338 // There is another string table for the source URIs. Skip it as well. | 1481 // There is another string table for the source URIs. Skip it as well. |
339 list_length = ReadListLength(); | 1482 list_length = ReadListLength(); // read list length. |
340 end_offset = 0; | 1483 end_offset = 0; |
341 for (intptr_t i = 0; i < list_length; ++i) { | 1484 for (intptr_t i = 0; i < list_length; ++i) { |
342 end_offset = ReadUInt(); | 1485 end_offset = ReadUInt(); // read ith offset. |
343 } | 1486 } |
344 SkipBytes(end_offset); | 1487 SkipBytes(end_offset); |
345 | 1488 |
346 // Source code table | 1489 // Source code table |
347 for (intptr_t i = 0; i < list_length; ++i) { | 1490 for (intptr_t i = 0; i < list_length; ++i) { |
348 // Source code | 1491 // Source code |
349 intptr_t bytes = ReadUInt(); | 1492 intptr_t bytes = ReadUInt(); // read ith byte length. |
350 SkipBytes(bytes); | 1493 SkipBytes(bytes); // read ith souce code package. |
351 | 1494 |
352 // Line starts table | 1495 // Line starts table |
353 intptr_t line_count = ReadUInt(); | 1496 intptr_t line_count = ReadUInt(); // read list length. |
354 for (intptr_t j = 0; j < line_count; ++j) { | 1497 for (intptr_t j = 0; j < line_count; ++j) { |
355 ReadUInt(); | 1498 ReadUInt(); // read jth line start. |
356 } | 1499 } |
357 } | 1500 } |
358 | 1501 |
359 // Now at canonical names table. | 1502 // Now at canonical names table. |
360 canonical_names_size_ = ReadUInt(); | 1503 canonical_names_size_ = ReadUInt(); // read number of canonical names. |
361 canonical_names_ = new CanonicalName*[canonical_names_size_]; | 1504 canonical_names_ = new CanonicalName*[canonical_names_size_]; |
362 canonical_names_next_offset_ = ReaderOffset(); | 1505 canonical_names_next_offset_ = ReaderOffset(); |
363 } | 1506 } |
364 | 1507 |
365 SetOffset(canonical_names_next_offset_); | 1508 SetOffset(canonical_names_next_offset_); |
366 for (; canonical_names_entries_read_ <= index; | 1509 for (; canonical_names_entries_read_ <= index; |
367 ++canonical_names_entries_read_) { | 1510 ++canonical_names_entries_read_) { |
368 intptr_t biased_parent_index = ReadUInt(); | 1511 intptr_t biased_parent_index = ReadUInt(); // read parent index. |
369 CanonicalName* parent; | 1512 CanonicalName* parent; |
370 if (biased_parent_index != 0) { | 1513 if (biased_parent_index != 0) { |
371 parent = canonical_names_[biased_parent_index - 1]; | 1514 parent = canonical_names_[biased_parent_index - 1]; |
372 } else { | 1515 } else { |
373 if (canonical_names_entries_read_ == 0) { | 1516 if (canonical_names_entries_read_ == 0) { |
374 parent = CanonicalName::NewRoot(); | 1517 parent = CanonicalName::NewRoot(); |
375 } else { | 1518 } else { |
376 parent = canonical_names_[0]->parent(); | 1519 parent = canonical_names_[0]->parent(); |
377 } | 1520 } |
378 } | 1521 } |
379 ASSERT(parent != NULL); | 1522 ASSERT(parent != NULL); |
380 intptr_t name_index = ReadUInt(); | 1523 intptr_t name_index = ReadUInt(); // read name index. |
381 CanonicalName* canonical_name = parent->AddChild(name_index); | 1524 CanonicalName* canonical_name = parent->AddChild(name_index); |
382 canonical_names_[canonical_names_entries_read_] = canonical_name; | 1525 canonical_names_[canonical_names_entries_read_] = canonical_name; |
383 } | 1526 } |
384 | 1527 |
385 canonical_names_next_offset_ = ReaderOffset(); | 1528 canonical_names_next_offset_ = ReaderOffset(); |
386 | 1529 |
387 SetOffset(saved_offset); | 1530 SetOffset(saved_offset); |
388 return canonical_names_[index]; | 1531 return canonical_names_[index]; |
389 } | 1532 } |
390 | 1533 |
1534 intptr_t StreamingFlowGraphBuilder::ReadNameAsStringIndex() { | |
1535 intptr_t name_index = ReadUInt(); // read name index. | |
1536 if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { | |
1537 ReadUInt(); // read library index. | |
1538 } | |
1539 return name_index; | |
1540 } | |
1541 | |
1542 const dart::String& StreamingFlowGraphBuilder::ReadNameAsMethodName() { | |
1543 intptr_t name_index = ReadUInt(); // read name index. | |
1544 if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { | |
1545 CanonicalName* library_reference = | |
1546 GetCanonicalName(ReadUInt()); // read library index. | |
1547 return H.DartMethodName(library_reference, name_index); | |
1548 } else { | |
1549 return H.DartMethodName(NULL, name_index); | |
1550 } | |
1551 } | |
1552 | |
1553 const dart::String& StreamingFlowGraphBuilder::ReadNameAsSetterName() { | |
1554 intptr_t name_index = ReadUInt(); // read name index. | |
1555 if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { | |
1556 CanonicalName* library_reference = | |
1557 GetCanonicalName(ReadUInt()); // read library index. | |
1558 return H.DartSetterName(library_reference, name_index); | |
1559 } else { | |
1560 return H.DartSetterName(NULL, name_index); | |
1561 } | |
1562 } | |
1563 | |
1564 const dart::String& StreamingFlowGraphBuilder::ReadNameAsGetterName() { | |
1565 intptr_t name_index = ReadUInt(); // read name index. | |
1566 if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { | |
1567 CanonicalName* library_reference = | |
1568 GetCanonicalName(ReadUInt()); // read library index. | |
1569 return H.DartGetterName(library_reference, name_index); | |
1570 } else { | |
1571 return H.DartGetterName(NULL, name_index); | |
1572 } | |
1573 } | |
1574 | |
1575 void StreamingFlowGraphBuilder::UpdateDirectDescendantPosition( | |
1576 TokenPosition position) { | |
1577 if (direct_descendant_position_ == TokenPosition::kLast) { | |
1578 direct_descendant_position_ = position; | |
1579 } | |
1580 } | |
1581 | |
1582 void StreamingFlowGraphBuilder::ResetDirectDescendantPosition() { | |
1583 direct_descendant_position_ = TokenPosition::kLast; | |
1584 } | |
391 | 1585 |
392 intptr_t StreamingFlowGraphBuilder::ReaderOffset() { | 1586 intptr_t StreamingFlowGraphBuilder::ReaderOffset() { |
393 return reader_->offset(); | 1587 return reader_->offset(); |
394 } | 1588 } |
395 | 1589 |
396 | |
397 void StreamingFlowGraphBuilder::SetOffset(intptr_t offset) { | 1590 void StreamingFlowGraphBuilder::SetOffset(intptr_t offset) { |
398 reader_->set_offset(offset); | 1591 reader_->set_offset(offset); |
399 } | 1592 } |
400 | 1593 |
401 | |
402 void StreamingFlowGraphBuilder::SkipBytes(intptr_t bytes) { | 1594 void StreamingFlowGraphBuilder::SkipBytes(intptr_t bytes) { |
403 reader_->set_offset(ReaderOffset() + bytes); | 1595 reader_->set_offset(ReaderOffset() + bytes); |
404 } | 1596 } |
405 | 1597 |
1598 bool StreamingFlowGraphBuilder::ReadBool() { | |
1599 return reader_->ReadBool(); | |
1600 } | |
1601 | |
1602 uint8_t StreamingFlowGraphBuilder::ReadByte() { | |
1603 return reader_->ReadByte(); | |
1604 } | |
406 | 1605 |
407 uint32_t StreamingFlowGraphBuilder::ReadUInt() { | 1606 uint32_t StreamingFlowGraphBuilder::ReadUInt() { |
408 return reader_->ReadUInt(); | 1607 return reader_->ReadUInt(); |
409 } | 1608 } |
410 | 1609 |
1610 uint32_t StreamingFlowGraphBuilder::PeekUInt() { | |
1611 intptr_t offset = ReaderOffset(); | |
1612 uint32_t result = reader_->ReadUInt(); | |
1613 SetOffset(offset); | |
1614 return result; | |
1615 } | |
411 | 1616 |
412 intptr_t StreamingFlowGraphBuilder::ReadListLength() { | 1617 intptr_t StreamingFlowGraphBuilder::ReadListLength() { |
413 return reader_->ReadListLength(); | 1618 return reader_->ReadListLength(); |
414 } | 1619 } |
415 | 1620 |
1621 void StreamingFlowGraphBuilder::SkipDartType() { | |
1622 Tag tag = ReadTag(); | |
1623 switch (tag) { | |
1624 case kInvalidType: | |
1625 case kDynamicType: | |
1626 case kVoidType: | |
1627 // those contain nothing. | |
1628 return; | |
1629 case kInterfaceType: | |
1630 SkipInterfaceType(false); | |
1631 return; | |
1632 case kSimpleInterfaceType: | |
1633 SkipInterfaceType(true); | |
1634 return; | |
1635 case kFunctionType: | |
1636 SkipFunctionType(false); | |
1637 return; | |
1638 case kSimpleFunctionType: | |
1639 SkipFunctionType(true); | |
1640 return; | |
1641 case kTypeParameterType: | |
1642 ReadUInt(); // read index for parameter. | |
1643 ReadUInt(); // binary offset. | |
1644 return; | |
1645 default: | |
1646 UNREACHABLE(); | |
1647 } | |
1648 } | |
1649 | |
1650 void StreamingFlowGraphBuilder::SkipOptionalDartType() { | |
1651 Tag tag = ReadTag(); // read tag. | |
1652 if (tag == kNothing) { | |
1653 return; | |
1654 } | |
1655 ASSERT(tag == kSomething); | |
1656 | |
1657 SkipDartType(); // read type. | |
1658 } | |
1659 | |
1660 void StreamingFlowGraphBuilder::SkipInterfaceType(bool simple) { | |
1661 ReadUInt(); // read klass_name. | |
1662 if (!simple) { | |
1663 intptr_t length = ReadListLength(); // read number of types. | |
1664 for (intptr_t i = 0; i < length; ++i) { | |
1665 SkipDartType(); // skip the ith type. | |
1666 } | |
1667 } | |
1668 } | |
1669 | |
1670 void StreamingFlowGraphBuilder::SkipFunctionType(bool simple) { | |
1671 if (!simple) { | |
1672 intptr_t list_length = | |
1673 ReadListLength(); // read type_parameters list length. | |
1674 for (int i = 0; i < list_length; ++i) { | |
1675 ReadUInt(); // read string index (name). | |
jensj
2017/05/04 10:13:05
I've added the missing "SkipDartType();" locally..
| |
1676 } | |
1677 ReadUInt(); // read required parameter count. | |
1678 ReadUInt(); // read total parameter count. | |
1679 } | |
1680 | |
1681 const intptr_t positional_count = | |
1682 ReadListLength(); // read positional_parameters list length. | |
1683 for (intptr_t i = 0; i < positional_count; ++i) { | |
1684 SkipDartType(); // read ith positional parameter. | |
1685 } | |
1686 | |
1687 if (!simple) { | |
1688 const intptr_t named_count = | |
1689 ReadListLength(); // read named_parameters list length. | |
1690 for (intptr_t i = 0; i < named_count; ++i) { | |
1691 ReadUInt(); // read string reference (i.e. named_parameters[i].name). | |
1692 SkipDartType(); // read named_parameters[i].type. | |
1693 } | |
1694 } | |
1695 | |
1696 SkipDartType(); // read return type. | |
1697 } | |
1698 | |
1699 void StreamingFlowGraphBuilder::SkipExpression() { | |
1700 uint8_t payload = 0; | |
1701 Tag tag = ReadTag(&payload); | |
1702 switch (tag) { | |
1703 case kInvalidExpression: | |
1704 return; | |
1705 case kVariableGet: | |
1706 ReadPosition(); // read position. | |
1707 ReadUInt(); // read kernel position. | |
1708 ReadUInt(); // read relative variable index. | |
1709 SkipOptionalDartType(); // read promoted type. | |
1710 return; | |
1711 case kSpecializedVariableGet: | |
1712 ReadPosition(); // read position. | |
1713 ReadUInt(); // read kernel position. | |
1714 return; | |
1715 case kVariableSet: | |
1716 ReadPosition(); // read position. | |
1717 ReadUInt(); // read kernel position. | |
1718 ReadUInt(); // read relative variable index. | |
1719 SkipExpression(); // read expression. | |
1720 return; | |
1721 case kSpecializedVariableSet: | |
1722 ReadPosition(); // read position. | |
1723 ReadUInt(); // read kernel position. | |
1724 SkipExpression(); // read expression. | |
1725 return; | |
1726 case kPropertyGet: | |
1727 ReadPosition(); // read position. | |
1728 SkipExpression(); // read receiver. | |
1729 SkipName(); // read name. | |
1730 ReadUInt(); // Read unused "interface_target_reference". | |
1731 return; | |
1732 case kPropertySet: | |
1733 ReadPosition(); // read position. | |
1734 SkipExpression(); // read receiver. | |
1735 SkipName(); // read name. | |
1736 SkipExpression(); // read value. | |
1737 ReadUInt(); // read unused "interface_target_reference". | |
1738 return; | |
1739 case kDirectPropertyGet: | |
1740 ReadPosition(); // read position. | |
1741 SkipExpression(); // read receiver. | |
1742 ReadUInt(); // read target_reference. | |
1743 return; | |
1744 case kDirectPropertySet: | |
1745 ReadPosition(); // read position. | |
1746 SkipExpression(); // read receiver. | |
1747 ReadUInt(); // read target_reference. | |
1748 SkipExpression(); // read value· | |
1749 return; | |
1750 case kStaticGet: | |
1751 ReadPosition(); // read position. | |
1752 ReadUInt(); // read target_reference. | |
1753 return; | |
1754 case kStaticSet: | |
1755 ReadPosition(); // read position. | |
1756 ReadUInt(); // read target_reference. | |
1757 SkipExpression(); // read expression. | |
1758 return; | |
1759 case kMethodInvocation: | |
1760 ReadPosition(); // read position. | |
1761 SkipExpression(); // read receiver. | |
1762 SkipName(); // read name. | |
1763 SkipArguments(); // read arguments. | |
1764 ReadUInt(); // read unused "interface_target_reference". | |
1765 return; | |
1766 case kDirectMethodInvocation: | |
1767 SkipExpression(); // read receiver. | |
1768 ReadUInt(); // read target_reference. | |
1769 SkipArguments(); // read arguments. | |
1770 return; | |
1771 case kStaticInvocation: | |
1772 case kConstStaticInvocation: | |
1773 ReadPosition(); // read position. | |
1774 ReadUInt(); // read procedure_reference. | |
1775 SkipArguments(); // read arguments. | |
1776 return; | |
1777 case kConstructorInvocation: | |
1778 case kConstConstructorInvocation: | |
1779 ReadPosition(); // read position. | |
1780 ReadUInt(); // read target_reference. | |
1781 SkipArguments(); // read arguments. | |
1782 return; | |
1783 case kNot: | |
1784 SkipExpression(); // read expression. | |
1785 return; | |
1786 case kLogicalExpression: | |
1787 SkipExpression(); // read left. | |
1788 SkipBytes(1); // read operator. | |
1789 SkipExpression(); // read right. | |
1790 return; | |
1791 case kConditionalExpression: | |
1792 SkipExpression(); // read condition. | |
1793 SkipExpression(); // read then. | |
1794 SkipExpression(); // read ohterwise. | |
1795 SkipOptionalDartType(); // read unused static type. | |
1796 return; | |
1797 case kStringConcatenation: { | |
1798 ReadPosition(); // read position. | |
1799 intptr_t list_length = ReadListLength(); // read list length. | |
1800 for (intptr_t i = 0; i < list_length; ++i) { | |
1801 SkipExpression(); // read ith expression. | |
1802 } | |
1803 return; | |
1804 } | |
1805 case kIsExpression: | |
1806 ReadPosition(); // read position. | |
1807 SkipExpression(); // read operand. | |
1808 SkipDartType(); // read type. | |
1809 return; | |
1810 case kAsExpression: | |
1811 ReadPosition(); // read position. | |
1812 SkipExpression(); // read operand. | |
1813 SkipDartType(); // read type. | |
1814 return; | |
1815 case kSymbolLiteral: | |
1816 ReadUInt(); // read index into string table. | |
1817 return; | |
1818 case kTypeLiteral: | |
1819 SkipDartType(); // read type. | |
1820 return; | |
1821 case kThisExpression: | |
1822 return; | |
1823 case kRethrow: | |
1824 ReadPosition(); // read position. | |
1825 return; | |
1826 case kThrow: | |
1827 ReadPosition(); // read position. | |
1828 SkipExpression(); // read expression. | |
1829 return; | |
1830 case kListLiteral: | |
1831 case kConstListLiteral: { | |
1832 ReadPosition(); // read position. | |
1833 SkipDartType(); // read type. | |
1834 intptr_t list_length = ReadListLength(); // read list length. | |
1835 for (intptr_t i = 0; i < list_length; ++i) { | |
1836 SkipExpression(); // read ith expression. | |
1837 } | |
1838 return; | |
1839 } | |
1840 case kMapLiteral: | |
1841 case kConstMapLiteral: { | |
1842 ReadPosition(); // read position. | |
1843 SkipDartType(); // read key type. | |
1844 SkipDartType(); // read value type. | |
1845 intptr_t list_length = ReadListLength(); // read list length. | |
1846 for (intptr_t i = 0; i < list_length; ++i) { | |
1847 SkipExpression(); // read ith key. | |
1848 SkipExpression(); // read ith value. | |
1849 } | |
1850 return; | |
1851 } | |
1852 case kFunctionExpression: | |
1853 // TODO(jensj) | |
1854 UNIMPLEMENTED(); | |
1855 return; | |
1856 case kLet: | |
1857 SkipVariableDeclaration(); // read variable declaration. | |
1858 SkipExpression(); // read expression. | |
1859 return; | |
1860 case kBigIntLiteral: | |
1861 ReadUInt(); // read string reference. | |
1862 return; | |
1863 case kStringLiteral: | |
1864 ReadUInt(); // read string reference. | |
1865 return; | |
1866 case kSpecialIntLiteral: | |
1867 return; | |
1868 case kNegativeIntLiteral: | |
1869 ReadUInt(); // read value. | |
1870 return; | |
1871 case kPositiveIntLiteral: | |
1872 ReadUInt(); // read value. | |
1873 return; | |
1874 case kDoubleLiteral: | |
1875 ReadUInt(); // read index into string table. | |
1876 return; | |
1877 case kTrueLiteral: | |
1878 return; | |
1879 case kFalseLiteral: | |
1880 return; | |
1881 case kNullLiteral: | |
1882 return; | |
1883 default: | |
1884 UNREACHABLE(); | |
1885 } | |
1886 } | |
1887 | |
1888 void StreamingFlowGraphBuilder::SkipName() { | |
1889 intptr_t name_index = ReadUInt(); // read name index. | |
1890 if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') { | |
1891 ReadUInt(); // read library index. | |
1892 } | |
1893 } | |
1894 | |
1895 void StreamingFlowGraphBuilder::SkipArguments() { | |
1896 ReadUInt(); // read argument count. | |
1897 | |
1898 // List of types. | |
1899 intptr_t list_length = ReadListLength(); // read list length. | |
1900 for (intptr_t i = 0; i < list_length; ++i) { | |
1901 SkipDartType(); // read ith type. | |
1902 } | |
1903 | |
1904 // List of positional. | |
1905 list_length = ReadListLength(); // read list length. | |
1906 for (intptr_t i = 0; i < list_length; ++i) { | |
1907 SkipExpression(); // read ith expression. | |
1908 } | |
1909 | |
1910 // List of named. | |
1911 list_length = ReadListLength(); // read list length. | |
1912 for (intptr_t i = 0; i < list_length; ++i) { | |
1913 ReadUInt(); // read ith name index. | |
1914 SkipExpression(); // read ith expression. | |
1915 } | |
1916 } | |
1917 | |
1918 void StreamingFlowGraphBuilder::SkipVariableDeclaration() { | |
1919 ReadPosition(); // read position. | |
1920 ReadPosition(); // read equals position. | |
1921 ReadFlags(); // read flags. | |
1922 ReadUInt(); // read name index. | |
1923 SkipDartType(); // read type. | |
1924 Tag tag = ReadTag(); // read (first part of) initializer. | |
1925 if (tag == kSomething) { | |
1926 SkipExpression(); // read (actual) initializer. | |
1927 } | |
1928 } | |
416 | 1929 |
417 TokenPosition StreamingFlowGraphBuilder::ReadPosition(bool record) { | 1930 TokenPosition StreamingFlowGraphBuilder::ReadPosition(bool record) { |
418 return reader_->ReadPosition(record); | 1931 return reader_->ReadPosition(record); |
419 } | 1932 } |
420 | 1933 |
421 | |
422 Tag StreamingFlowGraphBuilder::ReadTag(uint8_t* payload) { | 1934 Tag StreamingFlowGraphBuilder::ReadTag(uint8_t* payload) { |
423 return reader_->ReadTag(payload); | 1935 return reader_->ReadTag(payload); |
424 } | 1936 } |
425 | 1937 |
1938 Tag StreamingFlowGraphBuilder::PeekTag(uint8_t* payload) { | |
1939 return reader_->PeekTag(payload); | |
1940 } | |
1941 | |
1942 word StreamingFlowGraphBuilder::ReadFlags() { | |
1943 return reader_->ReadFlags(); | |
1944 } | |
1945 | |
1946 void StreamingFlowGraphBuilder::loop_depth_inc() { | |
1947 ++flow_graph_builder_->loop_depth_; | |
1948 } | |
1949 | |
1950 void StreamingFlowGraphBuilder::loop_depth_dec() { | |
1951 --flow_graph_builder_->loop_depth_; | |
1952 } | |
1953 | |
1954 intptr_t StreamingFlowGraphBuilder::for_in_depth() { | |
1955 return flow_graph_builder_->for_in_depth_; | |
1956 } | |
1957 | |
1958 void StreamingFlowGraphBuilder::for_in_depth_inc() { | |
1959 ++flow_graph_builder_->for_in_depth_; | |
1960 } | |
1961 | |
1962 void StreamingFlowGraphBuilder::for_in_depth_dec() { | |
1963 --flow_graph_builder_->for_in_depth_; | |
1964 } | |
1965 | |
1966 void StreamingFlowGraphBuilder::catch_depth_inc() { | |
1967 ++flow_graph_builder_->catch_depth_; | |
1968 } | |
1969 | |
1970 void StreamingFlowGraphBuilder::catch_depth_dec() { | |
1971 --flow_graph_builder_->catch_depth_; | |
1972 } | |
1973 | |
1974 void StreamingFlowGraphBuilder::try_depth_inc() { | |
1975 ++flow_graph_builder_->try_depth_; | |
1976 } | |
1977 | |
1978 void StreamingFlowGraphBuilder::try_depth_dec() { | |
1979 --flow_graph_builder_->try_depth_; | |
1980 } | |
1981 | |
1982 intptr_t StreamingFlowGraphBuilder::CurrentTryIndex() { | |
1983 return flow_graph_builder_->CurrentTryIndex(); | |
1984 } | |
1985 | |
1986 intptr_t StreamingFlowGraphBuilder::AllocateTryIndex() { | |
1987 return flow_graph_builder_->AllocateTryIndex(); | |
1988 } | |
1989 | |
1990 LocalVariable* StreamingFlowGraphBuilder::CurrentException() { | |
1991 return flow_graph_builder_->CurrentException(); | |
1992 } | |
1993 | |
1994 LocalVariable* StreamingFlowGraphBuilder::CurrentStackTrace() { | |
1995 return flow_graph_builder_->CurrentStackTrace(); | |
1996 } | |
426 | 1997 |
427 CatchBlock* StreamingFlowGraphBuilder::catch_block() { | 1998 CatchBlock* StreamingFlowGraphBuilder::catch_block() { |
428 return flow_graph_builder_->catch_block_; | 1999 return flow_graph_builder_->catch_block_; |
429 } | 2000 } |
430 | 2001 |
2002 ActiveClass* StreamingFlowGraphBuilder::active_class() { | |
2003 return &flow_graph_builder_->active_class_; | |
2004 } | |
431 | 2005 |
432 ScopeBuildingResult* StreamingFlowGraphBuilder::scopes() { | 2006 ScopeBuildingResult* StreamingFlowGraphBuilder::scopes() { |
433 return flow_graph_builder_->scopes_; | 2007 return flow_graph_builder_->scopes_; |
434 } | 2008 } |
435 | 2009 |
436 | |
437 ParsedFunction* StreamingFlowGraphBuilder::parsed_function() { | 2010 ParsedFunction* StreamingFlowGraphBuilder::parsed_function() { |
438 return flow_graph_builder_->parsed_function_; | 2011 return flow_graph_builder_->parsed_function_; |
439 } | 2012 } |
440 | 2013 |
2014 TryFinallyBlock* StreamingFlowGraphBuilder::try_finally_block() { | |
2015 return flow_graph_builder_->try_finally_block_; | |
2016 } | |
2017 | |
2018 SwitchBlock* StreamingFlowGraphBuilder::switch_block() { | |
2019 return flow_graph_builder_->switch_block_; | |
2020 } | |
2021 | |
2022 BreakableBlock* StreamingFlowGraphBuilder::breakable_block() { | |
2023 return flow_graph_builder_->breakable_block_; | |
2024 } | |
2025 | |
2026 GrowableArray<YieldContinuation>& | |
2027 StreamingFlowGraphBuilder::yield_continuations() { | |
2028 return flow_graph_builder_->yield_continuations_; | |
2029 } | |
2030 | |
2031 Value* StreamingFlowGraphBuilder::stack() { | |
2032 return flow_graph_builder_->stack_; | |
2033 } | |
2034 | |
2035 Value* StreamingFlowGraphBuilder::Pop() { | |
2036 return flow_graph_builder_->Pop(); | |
2037 } | |
2038 | |
2039 Tag StreamingFlowGraphBuilder::PeekArgumentsFirstPositionalTag() { | |
2040 intptr_t offset = ReaderOffset(); | |
2041 ReadUInt(); // read number of arguments. | |
2042 | |
2043 // List of types. | |
2044 intptr_t list_length = ReadListLength(); // read list length. | |
2045 for (intptr_t i = 0; i < list_length; ++i) { | |
2046 SkipDartType(); // read ith type. | |
2047 } | |
2048 | |
2049 // List of positional. | |
2050 list_length = ReadListLength(); // read list length. | |
2051 for (intptr_t i = 0; i < list_length; ++i) { | |
2052 Tag tag = ReadTag(); // read first tag. | |
2053 SetOffset(offset); // reset offset so this was a peek. | |
2054 return tag; | |
2055 } | |
2056 | |
2057 UNREACHABLE(); | |
2058 return kNothing; | |
2059 } | |
2060 | |
2061 const TypeArguments& StreamingFlowGraphBuilder::PeekArgumentsInstantiatedType( | |
2062 const dart::Class& klass) { | |
2063 // read parts of arguments, then go back to before doing so. | |
2064 intptr_t offset = ReaderOffset(); | |
2065 ReadUInt(); // read argument count. | |
2066 intptr_t list_length = ReadListLength(); // read types list length. | |
2067 const TypeArguments& type_arguments = | |
2068 T.BuildInstantiatedTypeArguments(klass, list_length); // read types. | |
2069 SetOffset(offset); | |
2070 return type_arguments; | |
2071 } | |
2072 | |
2073 intptr_t StreamingFlowGraphBuilder::PeekArgumentsCount() { | |
2074 return PeekUInt(); | |
2075 } | |
2076 | |
2077 intptr_t StreamingFlowGraphBuilder::PeekArgumentsTypeCount() { | |
2078 intptr_t offset = ReaderOffset(); | |
2079 ReadUInt(); // read arguments count. | |
2080 intptr_t types_count = ReadListLength(); // read length of types list. | |
2081 SetOffset(offset); | |
2082 return types_count; | |
2083 } | |
2084 | |
2085 void StreamingFlowGraphBuilder::SkipArgumentsBeforeActualArguments() { | |
2086 ReadUInt(); // read arguments count. | |
2087 intptr_t types_count = ReadListLength(); | |
2088 for (intptr_t i = 0; i < types_count; ++i) { | |
2089 SkipDartType(); // read ith type. | |
2090 } | |
2091 } | |
2092 | |
2093 LocalVariable* StreamingFlowGraphBuilder::LookupVariable( | |
2094 intptr_t kernel_offset) { | |
2095 return flow_graph_builder_->LookupVariable(kernel_offset); | |
2096 } | |
2097 | |
2098 LocalVariable* StreamingFlowGraphBuilder::MakeTemporary() { | |
2099 return flow_graph_builder_->MakeTemporary(); | |
2100 } | |
2101 | |
2102 Token::Kind StreamingFlowGraphBuilder::MethodKind(const dart::String& name) { | |
2103 return flow_graph_builder_->MethodKind(name); | |
2104 } | |
2105 | |
2106 dart::RawFunction* StreamingFlowGraphBuilder::LookupMethodByMember( | |
2107 CanonicalName* target, | |
2108 const dart::String& method_name) { | |
2109 return flow_graph_builder_->LookupMethodByMember(target, method_name); | |
2110 } | |
2111 | |
2112 bool StreamingFlowGraphBuilder::NeedsDebugStepCheck(const Function& function, | |
2113 TokenPosition position) { | |
2114 return flow_graph_builder_->NeedsDebugStepCheck(function, position); | |
2115 } | |
2116 | |
2117 bool StreamingFlowGraphBuilder::NeedsDebugStepCheck(Value* value, | |
2118 TokenPosition position) { | |
2119 return flow_graph_builder_->NeedsDebugStepCheck(value, position); | |
2120 } | |
2121 | |
2122 void StreamingFlowGraphBuilder::InlineBailout(const char* reason) { | |
2123 flow_graph_builder_->InlineBailout(reason); | |
2124 } | |
441 | 2125 |
442 Fragment StreamingFlowGraphBuilder::DebugStepCheck(TokenPosition position) { | 2126 Fragment StreamingFlowGraphBuilder::DebugStepCheck(TokenPosition position) { |
443 return flow_graph_builder_->DebugStepCheck(position); | 2127 return flow_graph_builder_->DebugStepCheck(position); |
444 } | 2128 } |
445 | 2129 |
446 | |
447 Fragment StreamingFlowGraphBuilder::LoadLocal(LocalVariable* variable) { | 2130 Fragment StreamingFlowGraphBuilder::LoadLocal(LocalVariable* variable) { |
448 return flow_graph_builder_->LoadLocal(variable); | 2131 return flow_graph_builder_->LoadLocal(variable); |
449 } | 2132 } |
450 | 2133 |
2134 Fragment StreamingFlowGraphBuilder::Return(TokenPosition position) { | |
2135 return flow_graph_builder_->Return(position); | |
2136 } | |
451 | 2137 |
452 Fragment StreamingFlowGraphBuilder::PushArgument() { | 2138 Fragment StreamingFlowGraphBuilder::PushArgument() { |
453 return flow_graph_builder_->PushArgument(); | 2139 return flow_graph_builder_->PushArgument(); |
454 } | 2140 } |
455 | 2141 |
2142 Fragment StreamingFlowGraphBuilder::EvaluateAssertion() { | |
2143 return flow_graph_builder_->EvaluateAssertion(); | |
2144 } | |
456 | 2145 |
457 Fragment StreamingFlowGraphBuilder::RethrowException(TokenPosition position, | 2146 Fragment StreamingFlowGraphBuilder::RethrowException(TokenPosition position, |
458 int catch_try_index) { | 2147 int catch_try_index) { |
459 return flow_graph_builder_->RethrowException(position, catch_try_index); | 2148 return flow_graph_builder_->RethrowException(position, catch_try_index); |
460 } | 2149 } |
461 | 2150 |
462 | |
463 Fragment StreamingFlowGraphBuilder::ThrowNoSuchMethodError() { | 2151 Fragment StreamingFlowGraphBuilder::ThrowNoSuchMethodError() { |
464 return flow_graph_builder_->ThrowNoSuchMethodError(); | 2152 return flow_graph_builder_->ThrowNoSuchMethodError(); |
465 } | 2153 } |
466 | 2154 |
467 | |
468 Fragment StreamingFlowGraphBuilder::Constant(const Object& value) { | 2155 Fragment StreamingFlowGraphBuilder::Constant(const Object& value) { |
469 return flow_graph_builder_->Constant(value); | 2156 return flow_graph_builder_->Constant(value); |
470 } | 2157 } |
471 | 2158 |
472 | |
473 Fragment StreamingFlowGraphBuilder::IntConstant(int64_t value) { | 2159 Fragment StreamingFlowGraphBuilder::IntConstant(int64_t value) { |
474 return flow_graph_builder_->IntConstant(value); | 2160 return flow_graph_builder_->IntConstant(value); |
475 } | 2161 } |
476 | 2162 |
477 | |
478 Fragment StreamingFlowGraphBuilder::LoadStaticField() { | 2163 Fragment StreamingFlowGraphBuilder::LoadStaticField() { |
479 return flow_graph_builder_->LoadStaticField(); | 2164 return flow_graph_builder_->LoadStaticField(); |
480 } | 2165 } |
481 | 2166 |
482 | |
483 Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position, | 2167 Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position, |
484 const Function& target, | 2168 const Function& target, |
485 intptr_t argument_count) { | 2169 intptr_t argument_count) { |
486 return flow_graph_builder_->StaticCall(position, target, argument_count); | 2170 return flow_graph_builder_->StaticCall(position, target, argument_count); |
487 } | 2171 } |
488 | 2172 |
2173 Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position, | |
2174 const Function& target, | |
2175 intptr_t argument_count, | |
2176 const Array& argument_names) { | |
2177 return flow_graph_builder_->StaticCall(position, target, argument_count, | |
2178 argument_names); | |
2179 } | |
2180 | |
2181 Fragment StreamingFlowGraphBuilder::InstanceCall(TokenPosition position, | |
2182 const dart::String& name, | |
2183 Token::Kind kind, | |
2184 intptr_t argument_count, | |
2185 intptr_t num_args_checked) { | |
2186 return flow_graph_builder_->InstanceCall(position, name, kind, argument_count, | |
2187 num_args_checked); | |
2188 } | |
2189 | |
2190 Fragment StreamingFlowGraphBuilder::ThrowException(TokenPosition position) { | |
2191 return flow_graph_builder_->ThrowException(position); | |
2192 } | |
2193 | |
2194 Fragment StreamingFlowGraphBuilder::BooleanNegate() { | |
2195 return flow_graph_builder_->BooleanNegate(); | |
2196 } | |
2197 | |
2198 Fragment StreamingFlowGraphBuilder::TranslateInstantiatedTypeArguments( | |
2199 const TypeArguments& type_arguments) { | |
2200 return flow_graph_builder_->TranslateInstantiatedTypeArguments( | |
2201 type_arguments); | |
2202 } | |
2203 | |
2204 Fragment StreamingFlowGraphBuilder::StrictCompare(Token::Kind kind, | |
2205 bool number_check) { | |
2206 return flow_graph_builder_->StrictCompare(kind, number_check); | |
2207 } | |
2208 | |
2209 Fragment StreamingFlowGraphBuilder::AllocateObject(const dart::Class& klass, | |
2210 intptr_t argument_count) { | |
2211 return flow_graph_builder_->AllocateObject(klass, argument_count); | |
2212 } | |
2213 | |
2214 Fragment StreamingFlowGraphBuilder::InstanceCall(TokenPosition position, | |
2215 const dart::String& name, | |
2216 Token::Kind kind, | |
2217 intptr_t argument_count, | |
2218 const Array& argument_names, | |
2219 intptr_t num_args_checked) { | |
2220 return flow_graph_builder_->InstanceCall(position, name, kind, argument_count, | |
2221 argument_names, num_args_checked); | |
2222 } | |
2223 | |
2224 Fragment StreamingFlowGraphBuilder::StoreLocal(TokenPosition position, | |
2225 LocalVariable* variable) { | |
2226 return flow_graph_builder_->StoreLocal(position, variable); | |
2227 } | |
2228 | |
2229 Fragment StreamingFlowGraphBuilder::StoreStaticField(TokenPosition position, | |
2230 const dart::Field& field) { | |
2231 return flow_graph_builder_->StoreStaticField(position, field); | |
2232 } | |
2233 | |
2234 Fragment StreamingFlowGraphBuilder::StringInterpolate(TokenPosition position) { | |
2235 return flow_graph_builder_->StringInterpolate(position); | |
2236 } | |
2237 | |
2238 Fragment StreamingFlowGraphBuilder::StringInterpolateSingle( | |
2239 TokenPosition position) { | |
2240 return flow_graph_builder_->StringInterpolateSingle(position); | |
2241 } | |
2242 | |
2243 Fragment StreamingFlowGraphBuilder::ThrowTypeError() { | |
2244 return flow_graph_builder_->ThrowTypeError(); | |
2245 } | |
2246 | |
2247 Fragment StreamingFlowGraphBuilder::LoadInstantiatorTypeArguments() { | |
2248 return flow_graph_builder_->LoadInstantiatorTypeArguments(); | |
2249 } | |
2250 | |
2251 Fragment StreamingFlowGraphBuilder::LoadFunctionTypeArguments() { | |
2252 return flow_graph_builder_->LoadFunctionTypeArguments(); | |
2253 } | |
2254 | |
2255 Fragment StreamingFlowGraphBuilder::InstantiateType(const AbstractType& type) { | |
2256 return flow_graph_builder_->InstantiateType(type); | |
2257 } | |
2258 | |
2259 Fragment StreamingFlowGraphBuilder::CreateArray() { | |
2260 return flow_graph_builder_->CreateArray(); | |
2261 } | |
2262 | |
2263 Fragment StreamingFlowGraphBuilder::StoreIndexed(intptr_t class_id) { | |
2264 return flow_graph_builder_->StoreIndexed(class_id); | |
2265 } | |
2266 | |
2267 Fragment StreamingFlowGraphBuilder::CheckStackOverflow() { | |
2268 return flow_graph_builder_->CheckStackOverflow(); | |
2269 } | |
2270 | |
2271 Fragment StreamingFlowGraphBuilder::CloneContext() { | |
2272 return flow_graph_builder_->CloneContext(); | |
2273 } | |
2274 | |
2275 Fragment StreamingFlowGraphBuilder::TranslateFinallyFinalizers( | |
2276 TryFinallyBlock* outer_finally, | |
2277 intptr_t target_context_depth) { | |
2278 // TODO(jensj): TranslateFinallyFinalizers can move the readers offset. | |
2279 // For now we'll save it and restore it afterwards. | |
2280 intptr_t offset = ReaderOffset(); | |
2281 Fragment result = flow_graph_builder_->TranslateFinallyFinalizers( | |
2282 outer_finally, target_context_depth); | |
2283 SetOffset(offset); | |
2284 return result; | |
2285 } | |
2286 | |
2287 Fragment StreamingFlowGraphBuilder::BranchIfTrue( | |
2288 TargetEntryInstr** then_entry, | |
2289 TargetEntryInstr** otherwise_entry, | |
2290 bool negate) { | |
2291 return flow_graph_builder_->BranchIfTrue(then_entry, otherwise_entry, negate); | |
2292 } | |
2293 | |
2294 Fragment StreamingFlowGraphBuilder::BranchIfEqual( | |
2295 TargetEntryInstr** then_entry, | |
2296 TargetEntryInstr** otherwise_entry, | |
2297 bool negate) { | |
2298 return flow_graph_builder_->BranchIfEqual(then_entry, otherwise_entry, | |
2299 negate); | |
2300 } | |
2301 | |
2302 Fragment StreamingFlowGraphBuilder::BranchIfNull( | |
2303 TargetEntryInstr** then_entry, | |
2304 TargetEntryInstr** otherwise_entry, | |
2305 bool negate) { | |
2306 return flow_graph_builder_->BranchIfNull(then_entry, otherwise_entry, negate); | |
2307 } | |
2308 | |
2309 Fragment StreamingFlowGraphBuilder::CatchBlockEntry(const Array& handler_types, | |
2310 intptr_t handler_index, | |
2311 bool needs_stacktrace) { | |
2312 return flow_graph_builder_->CatchBlockEntry(handler_types, handler_index, | |
2313 needs_stacktrace); | |
2314 } | |
2315 | |
2316 Fragment StreamingFlowGraphBuilder::TryCatch(int try_handler_index) { | |
2317 return flow_graph_builder_->TryCatch(try_handler_index); | |
2318 } | |
2319 | |
2320 Fragment StreamingFlowGraphBuilder::Drop() { | |
2321 return flow_graph_builder_->Drop(); | |
2322 } | |
2323 | |
2324 Fragment StreamingFlowGraphBuilder::NullConstant() { | |
2325 return flow_graph_builder_->NullConstant(); | |
2326 } | |
2327 | |
2328 JoinEntryInstr* StreamingFlowGraphBuilder::BuildJoinEntry() { | |
2329 return flow_graph_builder_->BuildJoinEntry(); | |
2330 } | |
2331 | |
2332 JoinEntryInstr* StreamingFlowGraphBuilder::BuildJoinEntry(intptr_t try_index) { | |
2333 return flow_graph_builder_->BuildJoinEntry(try_index); | |
2334 } | |
2335 | |
2336 Fragment StreamingFlowGraphBuilder::Goto(JoinEntryInstr* destination) { | |
2337 return flow_graph_builder_->Goto(destination); | |
2338 } | |
2339 | |
2340 Fragment StreamingFlowGraphBuilder::BuildImplicitClosureCreation( | |
2341 const Function& target) { | |
2342 return flow_graph_builder_->BuildImplicitClosureCreation(target); | |
2343 } | |
2344 | |
2345 Fragment StreamingFlowGraphBuilder::CheckBooleanInCheckedMode() { | |
2346 return flow_graph_builder_->CheckBooleanInCheckedMode(); | |
2347 } | |
2348 | |
2349 Fragment StreamingFlowGraphBuilder::CheckAssignableInCheckedMode( | |
2350 const dart::AbstractType& dst_type, | |
2351 const dart::String& dst_name) { | |
2352 return flow_graph_builder_->CheckAssignableInCheckedMode(dst_type, dst_name); | |
2353 } | |
2354 | |
2355 Fragment StreamingFlowGraphBuilder::CheckVariableTypeInCheckedMode( | |
2356 intptr_t variable_kernel_position) { | |
2357 if (I->type_checks()) { | |
2358 LocalVariable* variable = LookupVariable(variable_kernel_position); | |
2359 return flow_graph_builder_->CheckVariableTypeInCheckedMode( | |
2360 variable->type(), variable->name()); | |
2361 } | |
2362 return Fragment(); | |
2363 } | |
2364 | |
2365 Fragment StreamingFlowGraphBuilder::CheckVariableTypeInCheckedMode( | |
2366 const AbstractType& dst_type, | |
2367 const dart::String& name_symbol) { | |
2368 return flow_graph_builder_->CheckVariableTypeInCheckedMode(dst_type, | |
2369 name_symbol); | |
2370 } | |
2371 | |
2372 Fragment StreamingFlowGraphBuilder::EnterScope(intptr_t kernel_offset, | |
2373 bool* new_context) { | |
2374 return flow_graph_builder_->EnterScope(kernel_offset, new_context); | |
2375 } | |
2376 | |
2377 Fragment StreamingFlowGraphBuilder::ExitScope(intptr_t kernel_offset) { | |
2378 return flow_graph_builder_->ExitScope(kernel_offset); | |
2379 } | |
2380 | |
2381 Fragment StreamingFlowGraphBuilder::TranslateCondition(bool* negate) { | |
2382 *negate = PeekTag() == kNot; | |
2383 if (*negate) { | |
2384 SkipBytes(1); // Skip Not tag, thus go directly to the inner expression. | |
2385 } | |
2386 Fragment instructions = BuildExpression(); // read expression. | |
2387 instructions += CheckBooleanInCheckedMode(); | |
2388 return instructions; | |
2389 } | |
2390 | |
2391 const TypeArguments& StreamingFlowGraphBuilder::BuildTypeArguments() { | |
2392 ReadUInt(); // read arguments count. | |
2393 intptr_t types_count = ReadListLength(); // read type count. | |
2394 return T.BuildTypeArguments(types_count); // read types. | |
2395 } | |
2396 | |
2397 Fragment StreamingFlowGraphBuilder::BuildArguments(Array* argument_names, | |
2398 intptr_t* argument_count, | |
2399 bool skip_push_arguments, | |
2400 bool do_drop) { | |
2401 intptr_t dummy; | |
2402 if (argument_count == NULL) argument_count = &dummy; | |
2403 *argument_count = ReadUInt(); // read arguments count. | |
2404 | |
2405 // List of types. | |
2406 intptr_t list_length = ReadListLength(); // read type count. | |
2407 for (intptr_t i = 0; i < list_length; ++i) { | |
2408 SkipDartType(); // read ith type. | |
2409 } | |
2410 | |
2411 return BuildArgumentsFromActualArguments(argument_names, skip_push_arguments, | |
2412 do_drop); | |
2413 } | |
2414 | |
2415 Fragment StreamingFlowGraphBuilder::BuildArgumentsFromActualArguments( | |
2416 Array* argument_names, | |
2417 bool skip_push_arguments, | |
2418 bool do_drop) { | |
2419 Fragment instructions; | |
2420 | |
2421 // List of positional. | |
2422 intptr_t list_length = ReadListLength(); // read list length. | |
2423 for (intptr_t i = 0; i < list_length; ++i) { | |
2424 instructions += BuildExpression(); // read ith expression. | |
2425 if (!skip_push_arguments) instructions += PushArgument(); | |
2426 if (do_drop) instructions += Drop(); | |
2427 } | |
2428 | |
2429 // List of named. | |
2430 list_length = ReadListLength(); // read list length. | |
2431 if (argument_names != NULL && list_length > 0) { | |
2432 *argument_names ^= Array::New(list_length, Heap::kOld); | |
2433 } | |
2434 for (intptr_t i = 0; i < list_length; ++i) { | |
2435 dart::String& name = H.DartSymbol(ReadUInt()); // read ith name index. | |
2436 instructions += BuildExpression(); // read ith expression. | |
2437 if (!skip_push_arguments) instructions += PushArgument(); | |
2438 if (do_drop) instructions += Drop(); | |
2439 if (argument_names != NULL) { | |
2440 argument_names->SetAt(i, name); | |
2441 } | |
2442 } | |
2443 | |
2444 return instructions; | |
2445 } | |
489 | 2446 |
490 Fragment StreamingFlowGraphBuilder::BuildInvalidExpression() { | 2447 Fragment StreamingFlowGraphBuilder::BuildInvalidExpression() { |
2448 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
Kevin Millikin (Google)
2017/05/11 10:38:36
How about an optional output parameter defaulting
jensj
2017/05/11 12:59:25
Done.
| |
2449 | |
491 // The frontend will take care of emitting normal errors (like | 2450 // The frontend will take care of emitting normal errors (like |
492 // [NoSuchMethodError]s) and only emit [InvalidExpression]s in very special | 2451 // [NoSuchMethodError]s) and only emit [InvalidExpression]s in very special |
493 // situations (e.g. an invalid annotation). | 2452 // situations (e.g. an invalid annotation). |
494 return ThrowNoSuchMethodError(); | 2453 return ThrowNoSuchMethodError(); |
495 } | 2454 } |
496 | 2455 |
2456 Fragment StreamingFlowGraphBuilder::BuildVariableGet() { | |
2457 UpdateDirectDescendantPosition(ReadPosition()); // read position. | |
2458 intptr_t variable_kernel_position = ReadUInt(); // read kernel position. | |
2459 ReadUInt(); // read relative variable index. | |
2460 SkipOptionalDartType(); // read promoted type. | |
2461 | |
2462 return LoadLocal(LookupVariable(variable_kernel_position)); | |
2463 } | |
2464 | |
2465 Fragment StreamingFlowGraphBuilder::BuildVariableGet(uint8_t payload) { | |
2466 UpdateDirectDescendantPosition(ReadPosition()); // read position. | |
2467 intptr_t variable_kernel_position = ReadUInt(); // read kernel position. | |
2468 return LoadLocal(LookupVariable(variable_kernel_position)); | |
2469 } | |
2470 | |
2471 Fragment StreamingFlowGraphBuilder::BuildVariableSet() { | |
2472 TokenPosition position = ReadPosition(); // read position. | |
2473 UpdateDirectDescendantPosition(position); | |
2474 | |
2475 intptr_t variable_kernel_position = ReadUInt(); // read kernel position. | |
2476 ReadUInt(); // read relative variable index. | |
2477 Fragment instructions = BuildExpression(); // read expression. | |
2478 | |
2479 if (NeedsDebugStepCheck(stack(), position)) { | |
2480 instructions = DebugStepCheck(position) + instructions; | |
2481 } | |
2482 instructions += CheckVariableTypeInCheckedMode(variable_kernel_position); | |
2483 instructions += | |
2484 StoreLocal(position, LookupVariable(variable_kernel_position)); | |
2485 return instructions; | |
2486 } | |
2487 | |
2488 Fragment StreamingFlowGraphBuilder::BuildVariableSet(uint8_t payload) { | |
2489 TokenPosition position = ReadPosition(); // read position. | |
2490 UpdateDirectDescendantPosition(position); | |
2491 | |
2492 intptr_t variable_kernel_position = ReadUInt(); // read kernel position. | |
2493 Fragment instructions = BuildExpression(); // read expression. | |
2494 | |
2495 if (NeedsDebugStepCheck(stack(), position)) { | |
2496 instructions = DebugStepCheck(position) + instructions; | |
2497 } | |
2498 instructions += CheckVariableTypeInCheckedMode(variable_kernel_position); | |
2499 instructions += | |
2500 StoreLocal(position, LookupVariable(variable_kernel_position)); | |
2501 | |
2502 return instructions; | |
2503 } | |
2504 | |
2505 Fragment StreamingFlowGraphBuilder::BuildPropertyGet() { | |
2506 TokenPosition position = ReadPosition(); // read position. | |
2507 UpdateDirectDescendantPosition(position); | |
2508 | |
2509 Fragment instructions = BuildExpression(); // read receiver. | |
2510 instructions += PushArgument(); | |
2511 | |
2512 const dart::String& getter_name = ReadNameAsGetterName(); // read name. | |
2513 ReadUInt(); // Read unused "interface_target_reference". | |
2514 | |
2515 return instructions + InstanceCall(position, getter_name, Token::kGET, 1); | |
2516 } | |
2517 | |
2518 Fragment StreamingFlowGraphBuilder::BuildPropertySet() { | |
2519 Fragment instructions(NullConstant()); | |
2520 LocalVariable* variable = MakeTemporary(); | |
2521 | |
2522 TokenPosition position = ReadPosition(); // read position. | |
2523 UpdateDirectDescendantPosition(position); | |
2524 | |
2525 instructions += BuildExpression(); // read receiver. | |
2526 instructions += PushArgument(); | |
2527 | |
2528 const dart::String& setter_name = ReadNameAsSetterName(); // read name. | |
2529 | |
2530 instructions += BuildExpression(); // read value. | |
2531 instructions += StoreLocal(TokenPosition::kNoSource, variable); | |
2532 instructions += PushArgument(); | |
2533 | |
2534 ReadUInt(); // read unused "interface_target_reference". | |
2535 | |
2536 instructions += InstanceCall(position, setter_name, Token::kSET, 2); | |
2537 return instructions + Drop(); | |
2538 } | |
2539 | |
2540 Fragment StreamingFlowGraphBuilder::BuildDirectPropertyGet() { | |
2541 TokenPosition position = ReadPosition(); // read position. | |
2542 UpdateDirectDescendantPosition(position); | |
2543 | |
2544 Fragment instructions = BuildExpression(); // read receiver. | |
2545 CanonicalName* kernel_name = | |
2546 GetCanonicalName(ReadUInt()); // read target_reference. | |
2547 | |
2548 Function& target = Function::ZoneHandle(Z); | |
2549 if (H.IsProcedure(kernel_name)) { | |
2550 if (H.IsGetter(kernel_name)) { | |
2551 target = LookupMethodByMember(kernel_name, H.DartGetterName(kernel_name)); | |
2552 } else { | |
2553 // Undo stack change for the BuildExpression. | |
2554 Pop(); | |
2555 | |
2556 target = LookupMethodByMember(kernel_name, H.DartMethodName(kernel_name)); | |
2557 target = target.ImplicitClosureFunction(); | |
2558 ASSERT(!target.IsNull()); | |
2559 return BuildImplicitClosureCreation(target); | |
2560 } | |
2561 } else { | |
2562 ASSERT(H.IsField(kernel_name)); | |
2563 const dart::String& getter_name = H.DartGetterName(kernel_name); | |
2564 target = LookupMethodByMember(kernel_name, getter_name); | |
2565 ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction()); | |
2566 } | |
2567 | |
2568 instructions += PushArgument(); | |
2569 return instructions + StaticCall(position, target, 1); | |
2570 } | |
2571 | |
2572 Fragment StreamingFlowGraphBuilder::BuildDirectPropertySet() { | |
2573 TokenPosition position = ReadPosition(); // read position. | |
2574 UpdateDirectDescendantPosition(position); | |
2575 | |
2576 Fragment instructions(NullConstant()); | |
2577 LocalVariable* value = MakeTemporary(); | |
2578 | |
2579 instructions += BuildExpression(); // read receiver. | |
2580 instructions += PushArgument(); | |
2581 | |
2582 CanonicalName* target_reference = | |
2583 GetCanonicalName(ReadUInt()); // read target_reference. | |
2584 const dart::String& method_name = H.DartSetterName(target_reference); | |
2585 const Function& target = Function::ZoneHandle( | |
2586 Z, LookupMethodByMember(target_reference, method_name)); | |
2587 ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction()); | |
2588 | |
2589 instructions += BuildExpression(); // read value. | |
2590 instructions += StoreLocal(TokenPosition::kNoSource, value); | |
2591 instructions += PushArgument(); | |
2592 | |
2593 instructions += StaticCall(position, target, 2); | |
2594 | |
2595 return instructions + Drop(); | |
2596 } | |
497 | 2597 |
498 Fragment StreamingFlowGraphBuilder::BuildStaticGet() { | 2598 Fragment StreamingFlowGraphBuilder::BuildStaticGet() { |
499 intptr_t saved_offset = ReaderOffset() - 1; // Include the tag. | 2599 intptr_t offset = ReaderOffset() - 1; // Include the tag. |
500 TokenPosition position = ReadPosition(); | 2600 |
501 int canonical_name_index = ReadUInt(); | 2601 TokenPosition position = ReadPosition(); // read position. |
2602 UpdateDirectDescendantPosition(position); | |
2603 | |
2604 intptr_t canonical_name_index = ReadUInt(); // read target_reference. | |
502 CanonicalName* target = GetCanonicalName(canonical_name_index); | 2605 CanonicalName* target = GetCanonicalName(canonical_name_index); |
503 | 2606 |
504 if (H.IsField(target)) { | 2607 if (H.IsField(target)) { |
505 const dart::Field& field = | 2608 const dart::Field& field = |
506 dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(target)); | 2609 dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(target)); |
507 if (field.is_const()) { | 2610 if (field.is_const()) { |
508 SetOffset(saved_offset); // EvaluateExpression needs the tag. | 2611 return Constant(constant_evaluator_.EvaluateExpression(offset)); |
509 return Constant(constant_evaluator_.EvaluateExpression()); | |
510 } else { | 2612 } else { |
511 const dart::Class& owner = dart::Class::Handle(Z, field.Owner()); | 2613 const dart::Class& owner = dart::Class::Handle(Z, field.Owner()); |
512 const dart::String& getter_name = H.DartGetterName(target); | 2614 const dart::String& getter_name = H.DartGetterName(target); |
513 const Function& getter = | 2615 const Function& getter = |
514 Function::ZoneHandle(Z, owner.LookupStaticFunction(getter_name)); | 2616 Function::ZoneHandle(Z, owner.LookupStaticFunction(getter_name)); |
515 if (getter.IsNull() || !field.has_initializer()) { | 2617 if (getter.IsNull() || !field.has_initializer()) { |
516 Fragment instructions = Constant(field); | 2618 Fragment instructions = Constant(field); |
517 return instructions + LoadStaticField(); | 2619 return instructions + LoadStaticField(); |
518 } else { | 2620 } else { |
519 return StaticCall(position, getter, 0); | 2621 return StaticCall(position, getter, 0); |
520 } | 2622 } |
521 } | 2623 } |
522 } else { | 2624 } else { |
523 const Function& function = | 2625 const Function& function = |
524 Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target)); | 2626 Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target)); |
525 | 2627 |
526 if (H.IsGetter(target)) { | 2628 if (H.IsGetter(target)) { |
527 return StaticCall(position, function, 0); | 2629 return StaticCall(position, function, 0); |
528 } else if (H.IsMethod(target)) { | 2630 } else if (H.IsMethod(target)) { |
529 SetOffset(saved_offset); // EvaluateExpression needs the tag. | 2631 return Constant(constant_evaluator_.EvaluateExpression(offset)); |
530 return Constant(constant_evaluator_.EvaluateExpression()); | |
531 } else { | 2632 } else { |
532 UNIMPLEMENTED(); | 2633 UNIMPLEMENTED(); |
533 } | 2634 } |
534 } | 2635 } |
535 | 2636 |
536 return Fragment(); | 2637 return Fragment(); |
537 } | 2638 } |
538 | 2639 |
2640 Fragment StreamingFlowGraphBuilder::BuildStaticSet() { | |
2641 TokenPosition position = ReadPosition(); // read position. | |
2642 UpdateDirectDescendantPosition(position); | |
2643 | |
2644 intptr_t canonical_name_index = ReadUInt(); // read target_reference. | |
2645 CanonicalName* target = GetCanonicalName(canonical_name_index); | |
2646 | |
2647 if (H.IsField(target)) { | |
2648 const dart::Field& field = | |
2649 dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(target)); | |
2650 const AbstractType& dst_type = AbstractType::ZoneHandle(Z, field.type()); | |
2651 Fragment instructions = BuildExpression(); // read expression. | |
2652 if (NeedsDebugStepCheck(stack(), position)) { | |
2653 instructions = DebugStepCheck(position) + instructions; | |
2654 } | |
2655 instructions += CheckAssignableInCheckedMode( | |
2656 dst_type, dart::String::ZoneHandle(Z, field.name())); | |
2657 LocalVariable* variable = MakeTemporary(); | |
2658 instructions += LoadLocal(variable); | |
2659 return instructions + StoreStaticField(position, field); | |
2660 } else { | |
2661 ASSERT(H.IsProcedure(target)); | |
2662 | |
2663 // Evaluate the expression on the right hand side. | |
2664 Fragment instructions = BuildExpression(); // read expression. | |
2665 LocalVariable* variable = MakeTemporary(); | |
2666 | |
2667 // Prepare argument. | |
2668 instructions += LoadLocal(variable); | |
2669 instructions += PushArgument(); | |
2670 | |
2671 // Invoke the setter function. | |
2672 const Function& function = | |
2673 Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target)); | |
2674 instructions += StaticCall(position, function, 1); | |
2675 | |
2676 // Drop the unused result & leave the stored value on the stack. | |
2677 return instructions + Drop(); | |
2678 } | |
2679 } | |
2680 | |
2681 static bool IsNumberLiteral(Tag tag) { | |
2682 return tag == kNegativeIntLiteral || tag == kPositiveIntLiteral || | |
2683 tag == kSpecialIntLiteral || tag == kDoubleLiteral; | |
2684 } | |
2685 | |
2686 Fragment StreamingFlowGraphBuilder::BuildMethodInvocation() { | |
2687 intptr_t offset = ReaderOffset() - 1; // Include the tag. | |
2688 TokenPosition position = ReadPosition(); // read position. | |
2689 UpdateDirectDescendantPosition(position); | |
2690 | |
2691 Tag receiver_tag = PeekTag(); // peek tag for receiver. | |
2692 if (IsNumberLiteral(receiver_tag)) { | |
2693 intptr_t before_branch_offset = ReaderOffset(); | |
2694 | |
2695 SkipExpression(); // read receiver (it's just a number literal). | |
2696 | |
2697 const dart::String& name = ReadNameAsMethodName(); // read name. | |
2698 const Token::Kind token_kind = MethodKind(name); | |
2699 intptr_t argument_count = PeekArgumentsCount() + 1; | |
2700 | |
2701 if ((argument_count == 1) && (token_kind == Token::kNEGATE)) { | |
2702 const Object& result = constant_evaluator_.EvaluateExpressionSafe(offset); | |
2703 if (!result.IsError()) { | |
2704 SkipArguments(); // read arguments (there are none). | |
2705 ReadUInt(); // read unused "interface_target_reference". | |
2706 return Constant(result); | |
2707 } | |
2708 } else if ((argument_count == 2) && | |
2709 Token::IsBinaryArithmeticOperator(token_kind) && | |
2710 IsNumberLiteral(PeekArgumentsFirstPositionalTag())) { | |
2711 const Object& result = constant_evaluator_.EvaluateExpressionSafe(offset); | |
2712 if (!result.IsError()) { | |
2713 SkipArguments(); | |
2714 ReadUInt(); // read unused "interface_target_reference". | |
2715 return Constant(result); | |
2716 } | |
2717 } | |
2718 | |
2719 SetOffset(before_branch_offset); | |
2720 } | |
2721 | |
2722 Fragment instructions = BuildExpression(); // read receiver. | |
2723 | |
2724 const dart::String& name = ReadNameAsMethodName(); // read name. | |
2725 const Token::Kind token_kind = MethodKind(name); | |
2726 | |
2727 // Detect comparison with null. | |
2728 if ((token_kind == Token::kEQ || token_kind == Token::kNE) && | |
2729 PeekArgumentsCount() == 1 && | |
2730 (receiver_tag == kNullLiteral || | |
2731 PeekArgumentsFirstPositionalTag() == kNullLiteral)) { | |
2732 // "==" or "!=" with null on either side. | |
2733 instructions += BuildArguments(NULL, NULL, true); // read arguments. | |
2734 ReadUInt(); // read unused "interface_target_reference". | |
2735 Token::Kind strict_cmp_kind = | |
2736 token_kind == Token::kEQ ? Token::kEQ_STRICT : Token::kNE_STRICT; | |
2737 return instructions + | |
2738 StrictCompare(strict_cmp_kind, /*number_check = */ true); | |
2739 } | |
2740 | |
2741 instructions += PushArgument(); // push receiver as argument. | |
2742 | |
2743 // TODO(28109) Support generic methods in the VM or reify them away. | |
2744 Array& argument_names = Array::ZoneHandle(Z); | |
2745 intptr_t argument_count; | |
2746 instructions += | |
2747 BuildArguments(&argument_names, &argument_count); // read arguments. | |
2748 ++argument_count; | |
2749 | |
2750 intptr_t num_args_checked = 1; | |
2751 // If we have a special operation (e.g. +/-/==) we mark both arguments as | |
2752 // to be checked. | |
2753 if (token_kind != Token::kILLEGAL) { | |
2754 ASSERT(argument_count <= 2); | |
2755 num_args_checked = argument_count; | |
2756 } | |
2757 | |
2758 instructions += InstanceCall(position, name, token_kind, argument_count, | |
2759 argument_names, num_args_checked); | |
2760 // Later optimization passes assume that result of a x.[]=(...) call is not | |
2761 // used. We must guarantee this invariant because violation will lead to an | |
2762 // illegal IL once we replace x.[]=(...) with a sequence that does not | |
2763 // actually produce any value. See http://dartbug.com/29135 for more details. | |
2764 if (name.raw() == Symbols::AssignIndexToken().raw()) { | |
2765 instructions += Drop(); | |
2766 instructions += NullConstant(); | |
2767 } | |
2768 | |
2769 ReadUInt(); // read unused "interface_target_reference". | |
2770 | |
2771 return instructions; | |
2772 } | |
2773 | |
2774 Fragment StreamingFlowGraphBuilder::BuildDirectMethodInvocation() { | |
2775 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
2776 | |
2777 // TODO(28109) Support generic methods in the VM or reify them away. | |
2778 Tag receiver_tag = PeekTag(); // peek tag for receiver. | |
2779 Fragment instructions = BuildExpression(); // read receiver. | |
2780 | |
2781 CanonicalName* kernel_name = | |
2782 GetCanonicalName(ReadUInt()); // read target_reference. | |
2783 const dart::String& method_name = H.DartProcedureName(kernel_name); | |
2784 const Token::Kind token_kind = MethodKind(method_name); | |
2785 | |
2786 // Detect comparison with null. | |
2787 if ((token_kind == Token::kEQ || token_kind == Token::kNE) && | |
2788 PeekArgumentsCount() == 1 && | |
2789 (receiver_tag == kNullLiteral || | |
2790 PeekArgumentsFirstPositionalTag() == kNullLiteral)) { | |
2791 // "==" or "!=" with null on either side. | |
2792 instructions += BuildArguments(NULL, NULL, true); // read arguments. | |
2793 Token::Kind strict_cmp_kind = | |
2794 token_kind == Token::kEQ ? Token::kEQ_STRICT : Token::kNE_STRICT; | |
2795 return instructions + | |
2796 StrictCompare(strict_cmp_kind, /*number_check = */ true); | |
2797 } | |
2798 | |
2799 instructions += PushArgument(); // push receiver as argument. | |
2800 | |
2801 const Function& target = | |
2802 Function::ZoneHandle(Z, LookupMethodByMember(kernel_name, method_name)); | |
2803 | |
2804 Array& argument_names = Array::ZoneHandle(Z); | |
2805 intptr_t argument_count; | |
2806 instructions += | |
2807 BuildArguments(&argument_names, &argument_count); // read arguments. | |
2808 ++argument_count; | |
2809 return instructions + StaticCall(TokenPosition::kNoSource, target, | |
2810 argument_count, argument_names); | |
2811 } | |
2812 | |
2813 Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(bool is_const) { | |
2814 TokenPosition position = ReadPosition(); // read position. | |
2815 UpdateDirectDescendantPosition(position); | |
2816 | |
2817 intptr_t canonical_name_index = ReadUInt(); // read procedure reference. | |
2818 intptr_t argument_count = PeekArgumentsCount(); | |
2819 | |
2820 CanonicalName* procedue_reference = GetCanonicalName(canonical_name_index); | |
2821 const Function& target = Function::ZoneHandle( | |
2822 Z, H.LookupStaticMethodByKernelProcedure(procedue_reference)); | |
2823 const dart::Class& klass = dart::Class::ZoneHandle(Z, target.Owner()); | |
2824 if (target.IsGenerativeConstructor() || target.IsFactory()) { | |
2825 // The VM requires a TypeArguments object as first parameter for | |
2826 // every factory constructor. | |
2827 ++argument_count; | |
2828 } | |
2829 | |
2830 Fragment instructions; | |
2831 LocalVariable* instance_variable = NULL; | |
2832 | |
2833 // If we cross the Kernel -> VM core library boundary, a [StaticInvocation] | |
2834 // can appear, but the thing we're calling is not a static method, but a | |
2835 // factory constructor. | |
2836 // The `H.LookupStaticmethodByKernelProcedure` will potentially resolve to the | |
2837 // forwarded constructor. | |
2838 // In that case we'll make an instance and pass it as first argument. | |
2839 // | |
2840 // TODO(27590): Get rid of this after we're using core libraries compiled | |
2841 // into Kernel. | |
2842 if (target.IsGenerativeConstructor()) { | |
2843 if (klass.NumTypeArguments() > 0) { | |
2844 const TypeArguments& type_arguments = | |
2845 PeekArgumentsInstantiatedType(klass); | |
2846 instructions += TranslateInstantiatedTypeArguments(type_arguments); | |
2847 instructions += PushArgument(); | |
2848 instructions += AllocateObject(klass, 1); | |
2849 } else { | |
2850 instructions += AllocateObject(klass, 0); | |
2851 } | |
2852 | |
2853 instance_variable = MakeTemporary(); | |
2854 | |
2855 instructions += LoadLocal(instance_variable); | |
2856 instructions += PushArgument(); | |
2857 } else if (target.IsFactory()) { | |
2858 // The VM requires currently a TypeArguments object as first parameter for | |
2859 // every factory constructor :-/ ! | |
2860 // | |
2861 // TODO(27590): Get rid of this after we're using core libraries compiled | |
2862 // into Kernel. | |
2863 const TypeArguments& type_arguments = PeekArgumentsInstantiatedType(klass); | |
2864 instructions += TranslateInstantiatedTypeArguments(type_arguments); | |
2865 instructions += PushArgument(); | |
2866 } else { | |
2867 // TODO(28109) Support generic methods in the VM or reify them away. | |
2868 } | |
2869 | |
2870 bool special_case_identical = | |
2871 klass.IsTopLevel() && (klass.library() == dart::Library::CoreLibrary()) && | |
2872 (target.name() == Symbols::Identical().raw()); | |
2873 | |
2874 Array& argument_names = Array::ZoneHandle(Z); | |
2875 instructions += BuildArguments(&argument_names, NULL, | |
2876 special_case_identical); // read arguments. | |
2877 ASSERT(target.AreValidArguments(argument_count, argument_names, NULL)); | |
2878 | |
2879 // Special case identical(x, y) call. | |
2880 // TODO(27590) consider moving this into the inliner and force inline it | |
2881 // there. | |
2882 if (special_case_identical) { | |
2883 ASSERT(argument_count == 2); | |
2884 instructions += StrictCompare(Token::kEQ_STRICT, /*number_check=*/true); | |
2885 } else { | |
2886 instructions += | |
2887 StaticCall(position, target, argument_count, argument_names); | |
2888 if (target.IsGenerativeConstructor()) { | |
2889 // Drop the result of the constructor call and leave [instance_variable] | |
2890 // on top-of-stack. | |
2891 instructions += Drop(); | |
2892 } | |
2893 } | |
2894 | |
2895 return instructions; | |
2896 } | |
2897 | |
2898 Fragment StreamingFlowGraphBuilder::BuildConstructorInvocation(bool is_const) { | |
2899 if (is_const) { | |
2900 intptr_t offset = ReaderOffset() - 1; // Include the tag. | |
2901 UpdateDirectDescendantPosition(ReadPosition()); | |
2902 | |
2903 SetOffset(offset); | |
2904 SkipExpression(); // read past this ConstructorInvocation. | |
2905 return Constant(constant_evaluator_.EvaluateConstructorInvocation(offset)); | |
2906 } | |
2907 | |
2908 TokenPosition position = ReadPosition(); // read position. | |
2909 UpdateDirectDescendantPosition(position); | |
2910 | |
2911 CanonicalName* kernel_name = | |
2912 GetCanonicalName(ReadUInt()); // read target_reference. | |
2913 | |
2914 dart::Class& klass = dart::Class::ZoneHandle( | |
2915 Z, H.LookupClassByKernelClass(H.EnclosingName(kernel_name))); | |
2916 | |
2917 Fragment instructions; | |
2918 | |
2919 // Check for malbounded-ness of type. | |
2920 if (I->type_checks()) { | |
2921 intptr_t offset = ReaderOffset(); | |
2922 | |
2923 const TypeArguments& type_arguments = BuildTypeArguments(); | |
2924 | |
2925 AbstractType& type = AbstractType::Handle( | |
2926 Z, Type::New(klass, type_arguments, TokenPosition::kNoSource)); | |
2927 type = ClassFinalizer::FinalizeType(klass, type); | |
2928 | |
2929 if (type.IsMalbounded()) { | |
2930 // Evaluate expressions for correctness. | |
2931 instructions += | |
2932 BuildArgumentsFromActualArguments(NULL, false, /*do_drop*/ true); | |
2933 | |
2934 // Throw an error & keep the [Value] on the stack. | |
2935 instructions += ThrowTypeError(); | |
2936 | |
2937 // Bail out early. | |
2938 return instructions; | |
2939 } | |
2940 | |
2941 SetOffset(offset); | |
2942 } | |
2943 | |
2944 if (klass.NumTypeArguments() > 0) { | |
2945 const TypeArguments& type_arguments = PeekArgumentsInstantiatedType(klass); | |
2946 if (!klass.IsGeneric()) { | |
2947 Type& type = Type::ZoneHandle(Z, T.ReceiverType(klass).raw()); | |
2948 | |
2949 // TODO(27590): Can we move this code into [ReceiverType]? | |
2950 type ^= ClassFinalizer::FinalizeType(*active_class()->klass, type, | |
2951 ClassFinalizer::kFinalize); | |
2952 ASSERT(!type.IsMalformedOrMalbounded()); | |
2953 | |
2954 TypeArguments& canonicalized_type_arguments = | |
2955 TypeArguments::ZoneHandle(Z, type.arguments()); | |
2956 canonicalized_type_arguments = | |
2957 canonicalized_type_arguments.Canonicalize(); | |
2958 instructions += Constant(canonicalized_type_arguments); | |
2959 } else { | |
2960 instructions += TranslateInstantiatedTypeArguments(type_arguments); | |
2961 } | |
2962 | |
2963 instructions += PushArgument(); | |
2964 instructions += AllocateObject(klass, 1); | |
2965 } else { | |
2966 instructions += AllocateObject(klass, 0); | |
2967 } | |
2968 LocalVariable* variable = MakeTemporary(); | |
2969 | |
2970 instructions += LoadLocal(variable); | |
2971 instructions += PushArgument(); | |
2972 | |
2973 Array& argument_names = Array::ZoneHandle(Z); | |
2974 intptr_t argument_count; | |
2975 instructions += | |
2976 BuildArguments(&argument_names, &argument_count); // read arguments. | |
2977 | |
2978 const Function& target = Function::ZoneHandle( | |
2979 Z, H.LookupConstructorByKernelConstructor(klass, kernel_name)); | |
2980 ++argument_count; | |
2981 instructions += StaticCall(position, target, argument_count, argument_names); | |
2982 return instructions + Drop(); | |
2983 } | |
2984 | |
2985 Fragment StreamingFlowGraphBuilder::BuildNot() { | |
2986 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
2987 | |
2988 Fragment instructions = BuildExpression(); // read expression. | |
2989 instructions += CheckBooleanInCheckedMode(); | |
2990 instructions += BooleanNegate(); | |
2991 return instructions; | |
2992 } | |
2993 | |
2994 Fragment StreamingFlowGraphBuilder::BuildLogicalExpression() { | |
2995 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
2996 | |
2997 bool negate; | |
2998 Fragment instructions = TranslateCondition(&negate); // read left. | |
2999 | |
3000 TargetEntryInstr* right_entry; | |
3001 TargetEntryInstr* constant_entry; | |
3002 LogicalOperator op = static_cast<LogicalOperator>(ReadByte()); | |
3003 | |
3004 if (op == kAnd) { | |
3005 instructions += BranchIfTrue(&right_entry, &constant_entry, negate); | |
3006 } else { | |
3007 instructions += BranchIfTrue(&constant_entry, &right_entry, negate); | |
3008 } | |
3009 | |
3010 Value* top = stack(); | |
3011 Fragment right_fragment(right_entry); | |
3012 right_fragment += TranslateCondition(&negate); // read right. | |
3013 | |
3014 right_fragment += Constant(Bool::True()); | |
3015 right_fragment += | |
3016 StrictCompare(negate ? Token::kNE_STRICT : Token::kEQ_STRICT); | |
3017 right_fragment += StoreLocal(TokenPosition::kNoSource, | |
3018 parsed_function()->expression_temp_var()); | |
3019 right_fragment += Drop(); | |
3020 | |
3021 ASSERT(top == stack()); | |
3022 Fragment constant_fragment(constant_entry); | |
3023 constant_fragment += Constant(Bool::Get(op == kOr)); | |
3024 constant_fragment += StoreLocal(TokenPosition::kNoSource, | |
3025 parsed_function()->expression_temp_var()); | |
3026 constant_fragment += Drop(); | |
3027 | |
3028 JoinEntryInstr* join = BuildJoinEntry(); | |
3029 right_fragment += Goto(join); | |
3030 constant_fragment += Goto(join); | |
3031 | |
3032 return Fragment(instructions.entry, join) + | |
3033 LoadLocal(parsed_function()->expression_temp_var()); | |
3034 } | |
3035 | |
3036 Fragment StreamingFlowGraphBuilder::BuildConditionalExpression() { | |
3037 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
3038 | |
3039 bool negate; | |
3040 Fragment instructions = TranslateCondition(&negate); // read condition. | |
3041 | |
3042 TargetEntryInstr* then_entry; | |
3043 TargetEntryInstr* otherwise_entry; | |
3044 instructions += BranchIfTrue(&then_entry, &otherwise_entry, negate); | |
3045 | |
3046 Value* top = stack(); | |
3047 Fragment then_fragment(then_entry); | |
3048 then_fragment += BuildExpression(); // read then. | |
3049 then_fragment += StoreLocal(TokenPosition::kNoSource, | |
3050 parsed_function()->expression_temp_var()); | |
3051 then_fragment += Drop(); | |
3052 ASSERT(stack() == top); | |
3053 | |
3054 Fragment otherwise_fragment(otherwise_entry); | |
3055 otherwise_fragment += BuildExpression(); // read otherwise. | |
3056 otherwise_fragment += StoreLocal(TokenPosition::kNoSource, | |
3057 parsed_function()->expression_temp_var()); | |
3058 otherwise_fragment += Drop(); | |
3059 ASSERT(stack() == top); | |
3060 | |
3061 JoinEntryInstr* join = BuildJoinEntry(); | |
3062 then_fragment += Goto(join); | |
3063 otherwise_fragment += Goto(join); | |
3064 | |
3065 SkipOptionalDartType(); // read unused static type. | |
3066 | |
3067 return Fragment(instructions.entry, join) + | |
3068 LoadLocal(parsed_function()->expression_temp_var()); | |
3069 } | |
3070 | |
3071 Fragment StreamingFlowGraphBuilder::BuildStringConcatenation() { | |
3072 TokenPosition position = ReadPosition(); // read position. | |
3073 UpdateDirectDescendantPosition(position); | |
3074 | |
3075 intptr_t length = ReadListLength(); // read list length. | |
3076 // Note: there will be "length" expressions. | |
3077 | |
3078 Fragment instructions; | |
3079 if (length == 1) { | |
3080 instructions += BuildExpression(); // read expression. | |
3081 instructions += StringInterpolateSingle(position); | |
3082 } else { | |
3083 // The type arguments for CreateArray. | |
3084 instructions += Constant(TypeArguments::ZoneHandle(Z)); | |
3085 instructions += IntConstant(length); | |
3086 instructions += CreateArray(); | |
3087 LocalVariable* array = MakeTemporary(); | |
3088 | |
3089 for (intptr_t i = 0; i < length; ++i) { | |
3090 instructions += LoadLocal(array); | |
3091 instructions += IntConstant(i); | |
3092 instructions += BuildExpression(); // read ith expression. | |
3093 instructions += StoreIndexed(kArrayCid); | |
3094 instructions += Drop(); | |
3095 } | |
3096 | |
3097 instructions += StringInterpolate(position); | |
3098 } | |
3099 | |
3100 return instructions; | |
3101 } | |
3102 | |
3103 Fragment StreamingFlowGraphBuilder::BuildIsExpression() { | |
3104 TokenPosition position = ReadPosition(); // read position. | |
3105 UpdateDirectDescendantPosition(position); | |
3106 | |
3107 Fragment instructions = BuildExpression(); // read operand. | |
3108 | |
3109 const AbstractType& type = T.BuildType(); // read type. | |
3110 | |
3111 // The VM does not like an instanceOf call with a dynamic type. We need to | |
3112 // special case this situation. | |
3113 const Type& object_type = Type::Handle(Z, Type::ObjectType()); | |
3114 | |
3115 if (type.IsMalformed()) { | |
3116 instructions += Drop(); | |
3117 instructions += ThrowTypeError(); | |
3118 return instructions; | |
3119 } | |
3120 | |
3121 if (type.IsInstantiated() && | |
3122 object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) { | |
3123 // Evaluate the expression on the left but ignore it's result. | |
3124 instructions += Drop(); | |
3125 | |
3126 // Let condition be always true. | |
3127 instructions += Constant(Bool::True()); | |
3128 } else { | |
3129 instructions += PushArgument(); | |
3130 | |
3131 // See if simple instanceOf is applicable. | |
3132 if (dart::FlowGraphBuilder::SimpleInstanceOfType(type)) { | |
3133 instructions += Constant(type); | |
3134 instructions += PushArgument(); // Type. | |
3135 instructions += InstanceCall(position, dart::Library::PrivateCoreLibName( | |
3136 Symbols::_simpleInstanceOf()), | |
3137 Token::kIS, 2, 2); // 2 checked arguments. | |
3138 return instructions; | |
3139 } | |
3140 | |
3141 if (!type.IsInstantiated(kCurrentClass)) { | |
3142 instructions += LoadInstantiatorTypeArguments(); | |
3143 } else { | |
3144 instructions += NullConstant(); | |
3145 } | |
3146 instructions += PushArgument(); // Instantiator type arguments. | |
3147 | |
3148 if (!type.IsInstantiated(kFunctions)) { | |
3149 instructions += LoadFunctionTypeArguments(); | |
3150 } else { | |
3151 instructions += NullConstant(); | |
3152 } | |
3153 instructions += PushArgument(); // Function type arguments. | |
3154 | |
3155 instructions += Constant(type); | |
3156 instructions += PushArgument(); // Type. | |
3157 | |
3158 instructions += InstanceCall( | |
3159 position, dart::Library::PrivateCoreLibName(Symbols::_instanceOf()), | |
3160 Token::kIS, 4); | |
3161 } | |
3162 return instructions; | |
3163 } | |
3164 | |
3165 Fragment StreamingFlowGraphBuilder::BuildAsExpression() { | |
3166 TokenPosition position = ReadPosition(); // read position. | |
3167 UpdateDirectDescendantPosition(position); | |
3168 | |
3169 Fragment instructions = BuildExpression(); // read operand. | |
3170 | |
3171 const AbstractType& type = T.BuildType(); // read type. | |
3172 | |
3173 // The VM does not like an Object_as call with a dynamic type. We need to | |
3174 // special case this situation. | |
3175 const Type& object_type = Type::Handle(Z, Type::ObjectType()); | |
3176 | |
3177 if (type.IsMalformed()) { | |
3178 instructions += Drop(); | |
3179 instructions += ThrowTypeError(); | |
3180 return instructions; | |
3181 } | |
3182 | |
3183 if (type.IsInstantiated() && | |
3184 object_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) { | |
3185 // We already evaluated the operand on the left and just leave it there as | |
3186 // the result of the `obj as dynamic` expression. | |
3187 } else { | |
3188 instructions += PushArgument(); | |
3189 | |
3190 if (!type.IsInstantiated(kCurrentClass)) { | |
3191 instructions += LoadInstantiatorTypeArguments(); | |
3192 } else { | |
3193 instructions += NullConstant(); | |
3194 } | |
3195 instructions += PushArgument(); // Instantiator type arguments. | |
3196 | |
3197 if (!type.IsInstantiated(kFunctions)) { | |
3198 instructions += LoadFunctionTypeArguments(); | |
3199 } else { | |
3200 instructions += NullConstant(); | |
3201 } | |
3202 instructions += PushArgument(); // Function type arguments. | |
3203 | |
3204 instructions += Constant(type); | |
3205 instructions += PushArgument(); // Type. | |
3206 | |
3207 instructions += InstanceCall( | |
3208 position, dart::Library::PrivateCoreLibName(Symbols::_as()), Token::kAS, | |
3209 4); | |
3210 } | |
3211 return instructions; | |
3212 } | |
539 | 3213 |
540 Fragment StreamingFlowGraphBuilder::BuildSymbolLiteral() { | 3214 Fragment StreamingFlowGraphBuilder::BuildSymbolLiteral() { |
541 SkipBytes(-1); // EvaluateExpression needs the tag. | 3215 UpdateDirectDescendantPosition(TokenPosition::kNoSource); |
542 return Constant(constant_evaluator_.EvaluateExpression()); | 3216 |
543 } | 3217 intptr_t offset = ReaderOffset() - 1; // EvaluateExpression needs the tag. |
544 | 3218 ReadUInt(); // read index into string table. |
3219 return Constant(constant_evaluator_.EvaluateExpression(offset)); | |
3220 } | |
3221 | |
3222 Fragment StreamingFlowGraphBuilder::BuildTypeLiteral() { | |
3223 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
3224 | |
3225 const AbstractType& type = T.BuildType(); // read type. | |
3226 if (type.IsMalformed()) H.ReportError("Malformed type literal"); | |
3227 | |
3228 Fragment instructions; | |
3229 if (type.IsInstantiated()) { | |
3230 instructions += Constant(type); | |
3231 } else { | |
3232 if (!type.IsInstantiated(kCurrentClass)) { | |
3233 instructions += LoadInstantiatorTypeArguments(); | |
3234 } else { | |
3235 instructions += NullConstant(); | |
3236 } | |
3237 if (!type.IsInstantiated(kFunctions)) { | |
3238 instructions += LoadFunctionTypeArguments(); | |
3239 } else { | |
3240 instructions += NullConstant(); | |
3241 } | |
3242 instructions += InstantiateType(type); | |
3243 } | |
3244 return instructions; | |
3245 } | |
545 | 3246 |
546 Fragment StreamingFlowGraphBuilder::BuildThisExpression() { | 3247 Fragment StreamingFlowGraphBuilder::BuildThisExpression() { |
3248 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
3249 | |
547 return LoadLocal(scopes()->this_variable); | 3250 return LoadLocal(scopes()->this_variable); |
548 } | 3251 } |
549 | 3252 |
550 | |
551 Fragment StreamingFlowGraphBuilder::BuildRethrow() { | 3253 Fragment StreamingFlowGraphBuilder::BuildRethrow() { |
552 TokenPosition position = ReadPosition(); | 3254 TokenPosition position = ReadPosition(); // read position. |
3255 UpdateDirectDescendantPosition(position); | |
3256 | |
553 Fragment instructions = DebugStepCheck(position); | 3257 Fragment instructions = DebugStepCheck(position); |
554 instructions += LoadLocal(catch_block()->exception_var()); | 3258 instructions += LoadLocal(catch_block()->exception_var()); |
555 instructions += PushArgument(); | 3259 instructions += PushArgument(); |
556 instructions += LoadLocal(catch_block()->stack_trace_var()); | 3260 instructions += LoadLocal(catch_block()->stack_trace_var()); |
557 instructions += PushArgument(); | 3261 instructions += PushArgument(); |
558 instructions += RethrowException(position, catch_block()->catch_try_index()); | 3262 instructions += RethrowException(position, catch_block()->catch_try_index()); |
559 | 3263 |
560 return instructions; | 3264 return instructions; |
561 } | 3265 } |
562 | 3266 |
3267 Fragment StreamingFlowGraphBuilder::BuildThrow() { | |
3268 TokenPosition position = ReadPosition(); // read position. | |
3269 UpdateDirectDescendantPosition(position); | |
3270 | |
3271 Fragment instructions; | |
3272 | |
3273 instructions += BuildExpression(); // read expression. | |
3274 | |
3275 if (NeedsDebugStepCheck(stack(), position)) { | |
3276 instructions = DebugStepCheck(position) + instructions; | |
3277 } | |
3278 instructions += PushArgument(); | |
3279 instructions += ThrowException(position); | |
3280 ASSERT(instructions.is_closed()); | |
3281 | |
3282 return instructions; | |
3283 } | |
3284 | |
3285 Fragment StreamingFlowGraphBuilder::BuildListLiteral(bool is_const) { | |
3286 if (is_const) { | |
3287 intptr_t offset = ReaderOffset() - 1; // Include the tag. | |
3288 UpdateDirectDescendantPosition(ReadPosition()); | |
3289 | |
3290 SetOffset(offset); | |
3291 SkipExpression(); // read past the ListLiteral. | |
3292 return Constant(constant_evaluator_.EvaluateListLiteral(offset)); | |
3293 } | |
3294 | |
3295 TokenPosition position = ReadPosition(); // read position. | |
3296 UpdateDirectDescendantPosition(position); | |
3297 | |
3298 const TypeArguments& type_arguments = T.BuildTypeArguments(1); // read type. | |
3299 intptr_t length = ReadListLength(); // read list length. | |
3300 // Note: there will be "length" expressions. | |
3301 | |
3302 // The type argument for the factory call. | |
3303 Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments); | |
3304 instructions += PushArgument(); | |
3305 if (length == 0) { | |
3306 instructions += Constant(Object::empty_array()); | |
3307 } else { | |
3308 // The type arguments for CreateArray. | |
3309 instructions += Constant(TypeArguments::ZoneHandle(Z)); | |
3310 instructions += IntConstant(length); | |
3311 instructions += CreateArray(); | |
3312 | |
3313 LocalVariable* array = MakeTemporary(); | |
3314 for (intptr_t i = 0; i < length; ++i) { | |
3315 instructions += LoadLocal(array); | |
3316 instructions += IntConstant(i); | |
3317 instructions += BuildExpression(); // read ith expression. | |
3318 instructions += StoreIndexed(kArrayCid); | |
3319 instructions += Drop(); | |
3320 } | |
3321 } | |
3322 instructions += PushArgument(); // The array. | |
3323 | |
3324 const dart::Class& factory_class = | |
3325 dart::Class::Handle(Z, dart::Library::LookupCoreClass(Symbols::List())); | |
3326 const Function& factory_method = Function::ZoneHandle( | |
3327 Z, factory_class.LookupFactory( | |
3328 dart::Library::PrivateCoreLibName(Symbols::ListLiteralFactory()))); | |
3329 | |
3330 return instructions + StaticCall(position, factory_method, 2); | |
3331 } | |
3332 | |
3333 Fragment StreamingFlowGraphBuilder::BuildMapLiteral(bool is_const) { | |
3334 if (is_const) { | |
3335 intptr_t offset = ReaderOffset() - 1; // Include the tag. | |
3336 UpdateDirectDescendantPosition(ReadPosition()); | |
3337 | |
3338 SetOffset(offset); | |
3339 SkipExpression(); // Read past the MapLiteral. | |
3340 return Constant(constant_evaluator_.EvaluateMapLiteral(offset)); | |
3341 } | |
3342 | |
3343 TokenPosition position = ReadPosition(); // read position. | |
3344 UpdateDirectDescendantPosition(position); | |
3345 | |
3346 const TypeArguments& type_arguments = | |
3347 T.BuildTypeArguments(2); // read key_type and value_type. | |
3348 | |
3349 // The type argument for the factory call `new Map<K, V>._fromLiteral(List)`. | |
3350 Fragment instructions = TranslateInstantiatedTypeArguments(type_arguments); | |
3351 instructions += PushArgument(); | |
3352 | |
3353 intptr_t length = ReadListLength(); // read list length. | |
3354 // Note: there will be "length" map entries (i.e. key and value expressions). | |
3355 | |
3356 if (length == 0) { | |
3357 instructions += Constant(Object::empty_array()); | |
3358 } else { | |
3359 // The type arguments for `new List<X>(int len)`. | |
3360 instructions += Constant(TypeArguments::ZoneHandle(Z)); | |
3361 | |
3362 // We generate a list of tuples, i.e. [key1, value1, ..., keyN, valueN]. | |
3363 instructions += IntConstant(2 * length); | |
3364 instructions += CreateArray(); | |
3365 | |
3366 LocalVariable* array = MakeTemporary(); | |
3367 for (intptr_t i = 0; i < length; ++i) { | |
3368 instructions += LoadLocal(array); | |
3369 instructions += IntConstant(2 * i); | |
3370 instructions += BuildExpression(); // read ith key. | |
3371 instructions += StoreIndexed(kArrayCid); | |
3372 instructions += Drop(); | |
3373 | |
3374 instructions += LoadLocal(array); | |
3375 instructions += IntConstant(2 * i + 1); | |
3376 instructions += BuildExpression(); // read ith value. | |
3377 instructions += StoreIndexed(kArrayCid); | |
3378 instructions += Drop(); | |
3379 } | |
3380 } | |
3381 instructions += PushArgument(); // The array. | |
3382 | |
3383 | |
3384 const dart::Class& map_class = | |
3385 dart::Class::Handle(Z, dart::Library::LookupCoreClass(Symbols::Map())); | |
3386 const Function& factory_method = Function::ZoneHandle( | |
3387 Z, map_class.LookupFactory( | |
3388 dart::Library::PrivateCoreLibName(Symbols::MapLiteralFactory()))); | |
3389 | |
3390 return instructions + StaticCall(position, factory_method, 2); | |
3391 } | |
3392 | |
3393 Fragment StreamingFlowGraphBuilder::BuildLet() { | |
3394 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
3395 | |
3396 Fragment instructions = BuildVariableDeclaration(false); // read variable. | |
3397 instructions += BuildExpression(); // read body. | |
3398 return instructions; | |
3399 } | |
3400 | |
563 | 3401 |
564 Fragment StreamingFlowGraphBuilder::BuildBigIntLiteral() { | 3402 Fragment StreamingFlowGraphBuilder::BuildBigIntLiteral() { |
565 const dart::String& value = H.DartString(ReadUInt()); | 3403 UpdateDirectDescendantPosition(TokenPosition::kNoSource); |
3404 | |
3405 const dart::String& value = | |
3406 H.DartString(ReadUInt()); // read string reference. | |
566 return Constant(Integer::ZoneHandle(Z, Integer::New(value, Heap::kOld))); | 3407 return Constant(Integer::ZoneHandle(Z, Integer::New(value, Heap::kOld))); |
567 } | 3408 } |
568 | 3409 |
569 | |
570 Fragment StreamingFlowGraphBuilder::BuildStringLiteral() { | 3410 Fragment StreamingFlowGraphBuilder::BuildStringLiteral() { |
571 intptr_t str_index = ReadUInt(); | 3411 UpdateDirectDescendantPosition(TokenPosition::kNoSource); |
3412 | |
3413 intptr_t str_index = ReadUInt(); // read string reference. | |
572 return Constant(H.DartSymbol(str_index)); | 3414 return Constant(H.DartSymbol(str_index)); |
573 } | 3415 } |
574 | 3416 |
575 | |
576 Fragment StreamingFlowGraphBuilder::BuildIntLiteral(uint8_t payload) { | 3417 Fragment StreamingFlowGraphBuilder::BuildIntLiteral(uint8_t payload) { |
3418 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
3419 | |
577 int64_t value = static_cast<int32_t>(payload) - SpecializedIntLiteralBias; | 3420 int64_t value = static_cast<int32_t>(payload) - SpecializedIntLiteralBias; |
578 return IntConstant(value); | 3421 return IntConstant(value); |
579 } | 3422 } |
580 | 3423 |
581 | |
582 Fragment StreamingFlowGraphBuilder::BuildIntLiteral(bool is_negative) { | 3424 Fragment StreamingFlowGraphBuilder::BuildIntLiteral(bool is_negative) { |
583 int64_t value = is_negative ? -static_cast<int64_t>(ReadUInt()) : ReadUInt(); | 3425 UpdateDirectDescendantPosition(TokenPosition::kNoSource); |
3426 | |
3427 int64_t value = is_negative ? -static_cast<int64_t>(ReadUInt()) | |
3428 : ReadUInt(); // read value. | |
584 return IntConstant(value); | 3429 return IntConstant(value); |
585 } | 3430 } |
586 | 3431 |
587 | |
588 Fragment StreamingFlowGraphBuilder::BuildDoubleLiteral() { | 3432 Fragment StreamingFlowGraphBuilder::BuildDoubleLiteral() { |
589 SkipBytes(-1); // EvaluateExpression needs the tag. | 3433 UpdateDirectDescendantPosition(TokenPosition::kNoSource); |
590 return Constant(constant_evaluator_.EvaluateExpression()); | 3434 |
591 } | 3435 intptr_t offset = ReaderOffset() - 1; // EvaluateExpression needs the tag. |
592 | 3436 ReadUInt(); // read index into string table. |
3437 return Constant(constant_evaluator_.EvaluateExpression(offset)); | |
3438 } | |
593 | 3439 |
594 Fragment StreamingFlowGraphBuilder::BuildBoolLiteral(bool value) { | 3440 Fragment StreamingFlowGraphBuilder::BuildBoolLiteral(bool value) { |
3441 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
3442 | |
595 return Constant(Bool::Get(value)); | 3443 return Constant(Bool::Get(value)); |
596 } | 3444 } |
597 | 3445 |
598 | |
599 Fragment StreamingFlowGraphBuilder::BuildNullLiteral() { | 3446 Fragment StreamingFlowGraphBuilder::BuildNullLiteral() { |
3447 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
3448 | |
600 return Constant(Instance::ZoneHandle(Z, Instance::null())); | 3449 return Constant(Instance::ZoneHandle(Z, Instance::null())); |
601 } | 3450 } |
602 | 3451 |
3452 Fragment StreamingFlowGraphBuilder::BuildInvalidStatement() { | |
3453 UpdateDirectDescendantPosition(TokenPosition::kNoSource); | |
3454 | |
3455 H.ReportError("Invalid statements not implemented yet!"); | |
3456 return Fragment(); | |
3457 } | |
3458 | |
3459 Fragment StreamingFlowGraphBuilder::BuildExpressionStatement() { | |
3460 Fragment instructions = BuildExpression(); // read expression. | |
3461 instructions += Drop(); | |
3462 return instructions; | |
3463 } | |
3464 | |
3465 Fragment StreamingFlowGraphBuilder::BuildBlock() { | |
3466 intptr_t offset = ReaderOffset() - 1; // Include the tag. | |
3467 | |
3468 Fragment instructions; | |
3469 | |
3470 instructions += EnterScope(offset); | |
3471 intptr_t list_length = ReadListLength(); // read number of statements. | |
3472 for (intptr_t i = 0; i < list_length; ++i) { | |
3473 if (instructions.is_open()) { | |
3474 instructions += BuildStatement(); // read ith statement. | |
3475 } else { | |
3476 SkipStatement(); // read ith statement. | |
3477 } | |
3478 } | |
3479 instructions += ExitScope(offset); | |
3480 | |
3481 return instructions; | |
3482 } | |
3483 | |
3484 Fragment StreamingFlowGraphBuilder::BuildEmptyStatement() { | |
3485 return Fragment(); | |
3486 } | |
3487 | |
3488 Fragment StreamingFlowGraphBuilder::BuildAssertStatement() { | |
3489 if (!I->asserts()) { | |
3490 intptr_t offset = ReaderOffset() - 1; // Include the tag. | |
3491 SetOffset(offset); | |
3492 SkipStatement(); // read this statement. | |
3493 return Fragment(); | |
3494 } | |
3495 | |
3496 TargetEntryInstr* then; | |
3497 TargetEntryInstr* otherwise; | |
3498 | |
3499 Fragment instructions; | |
3500 // Asserts can be of the following two kinds: | |
3501 // | |
3502 // * `assert(expr)` | |
3503 // * `assert(() { ... })` | |
3504 // | |
3505 // The call to `_AssertionError._evaluateAssertion()` will take care of both | |
3506 // and returns a boolean. | |
3507 instructions += BuildExpression(); // read condition. | |
3508 instructions += PushArgument(); | |
3509 instructions += EvaluateAssertion(); | |
3510 instructions += CheckBooleanInCheckedMode(); | |
3511 instructions += Constant(Bool::True()); | |
3512 instructions += BranchIfEqual(&then, &otherwise, false); | |
3513 | |
3514 const dart::Class& klass = dart::Class::ZoneHandle( | |
3515 Z, dart::Library::LookupCoreClass(Symbols::AssertionError())); | |
3516 ASSERT(!klass.IsNull()); | |
3517 const dart::Function& constructor = dart::Function::ZoneHandle( | |
3518 Z, klass.LookupConstructorAllowPrivate( | |
3519 H.DartSymbol("_AssertionError._create"))); | |
3520 ASSERT(!constructor.IsNull()); | |
3521 | |
3522 const dart::String& url = H.DartString( | |
3523 parsed_function()->function().ToLibNamePrefixedQualifiedCString(), | |
3524 Heap::kOld); | |
3525 | |
3526 // Create instance of _AssertionError | |
3527 Fragment otherwise_fragment(otherwise); | |
3528 otherwise_fragment += AllocateObject(klass, 0); | |
3529 LocalVariable* instance = MakeTemporary(); | |
3530 | |
3531 // Call _AssertionError._create constructor. | |
3532 otherwise_fragment += LoadLocal(instance); | |
3533 otherwise_fragment += PushArgument(); // this | |
3534 | |
3535 otherwise_fragment += Constant(H.DartString("<no message>", Heap::kOld)); | |
3536 otherwise_fragment += PushArgument(); // failedAssertion | |
3537 | |
3538 otherwise_fragment += Constant(url); | |
3539 otherwise_fragment += PushArgument(); // url | |
3540 | |
3541 otherwise_fragment += IntConstant(0); | |
3542 otherwise_fragment += PushArgument(); // line | |
3543 | |
3544 otherwise_fragment += IntConstant(0); | |
3545 otherwise_fragment += PushArgument(); // column | |
3546 | |
3547 Tag tag = ReadTag(); // read (first part of) message. | |
3548 if (tag == kSomething) { | |
3549 otherwise_fragment += BuildExpression(); // read (rest of) message. | |
3550 } else { | |
3551 otherwise_fragment += Constant(H.DartString("<no message>", Heap::kOld)); | |
3552 } | |
3553 otherwise_fragment += PushArgument(); // message | |
3554 | |
3555 otherwise_fragment += StaticCall(TokenPosition::kNoSource, constructor, 6); | |
3556 otherwise_fragment += Drop(); | |
3557 | |
3558 // Throw _AssertionError exception. | |
3559 otherwise_fragment += PushArgument(); | |
3560 otherwise_fragment += ThrowException(TokenPosition::kNoSource); | |
3561 otherwise_fragment += Drop(); | |
3562 | |
3563 return Fragment(instructions.entry, then); | |
3564 } | |
3565 | |
3566 Fragment StreamingFlowGraphBuilder::BuildLabeledStatement() { | |
3567 // There can be serveral cases: | |
3568 // | |
3569 // * the body contains a break | |
3570 // * the body doesn't contain a break | |
3571 // | |
3572 // * translating the body results in a closed fragment | |
3573 // * translating the body results in a open fragment | |
3574 // | |
3575 // => We will only know which case we are in after the body has been | |
3576 // traversed. | |
3577 | |
3578 BreakableBlock block(flow_graph_builder_); | |
3579 Fragment instructions = BuildStatement(); // read body. | |
3580 if (block.HadJumper()) { | |
3581 if (instructions.is_open()) { | |
3582 instructions += Goto(block.destination()); | |
3583 } | |
3584 return Fragment(instructions.entry, block.destination()); | |
3585 } else { | |
3586 return instructions; | |
3587 } | |
3588 } | |
3589 | |
3590 Fragment StreamingFlowGraphBuilder::BuildBreakStatement() { | |
3591 TokenPosition position = ReadPosition(); // read position. | |
3592 intptr_t target_index = ReadUInt(); // read target index. | |
3593 | |
3594 TryFinallyBlock* outer_finally = NULL; | |
3595 intptr_t target_context_depth = -1; | |
3596 JoinEntryInstr* destination = breakable_block()->BreakDestination( | |
3597 target_index, &outer_finally, &target_context_depth); | |
3598 | |
3599 Fragment instructions; | |
3600 instructions += | |
3601 TranslateFinallyFinalizers(outer_finally, target_context_depth); | |
3602 if (instructions.is_open()) { | |
3603 if (NeedsDebugStepCheck(parsed_function()->function(), position)) { | |
3604 instructions += DebugStepCheck(position); | |
3605 } | |
3606 instructions += Goto(destination); | |
3607 } | |
3608 return instructions; | |
3609 } | |
3610 | |
3611 Fragment StreamingFlowGraphBuilder::BuildWhileStatement() { | |
3612 loop_depth_inc(); | |
3613 bool negate; | |
3614 Fragment condition = TranslateCondition(&negate); // read condition. | |
3615 TargetEntryInstr* body_entry; | |
3616 TargetEntryInstr* loop_exit; | |
3617 condition += BranchIfTrue(&body_entry, &loop_exit, negate); | |
3618 | |
3619 Fragment body(body_entry); | |
3620 body += BuildStatement(); // read body. | |
3621 | |
3622 Instruction* entry; | |
3623 if (body.is_open()) { | |
3624 JoinEntryInstr* join = BuildJoinEntry(); | |
3625 body += Goto(join); | |
3626 | |
3627 Fragment loop(join); | |
3628 loop += CheckStackOverflow(); | |
3629 loop += condition; | |
3630 entry = new (Z) GotoInstr(join); | |
3631 } else { | |
3632 entry = condition.entry; | |
3633 } | |
3634 | |
3635 | |
3636 loop_depth_dec(); | |
3637 return Fragment(entry, loop_exit); | |
3638 } | |
3639 | |
3640 Fragment StreamingFlowGraphBuilder::BuildDoStatement() { | |
3641 loop_depth_inc(); | |
3642 Fragment body = BuildStatement(); // read body. | |
3643 | |
3644 if (body.is_closed()) { | |
3645 SkipExpression(); // read condition. | |
3646 loop_depth_dec(); | |
3647 return body; | |
3648 } | |
3649 | |
3650 bool negate; | |
3651 JoinEntryInstr* join = BuildJoinEntry(); | |
3652 Fragment loop(join); | |
3653 loop += CheckStackOverflow(); | |
3654 loop += body; | |
3655 loop += TranslateCondition(&negate); // read condition. | |
3656 TargetEntryInstr* loop_repeat; | |
3657 TargetEntryInstr* loop_exit; | |
3658 loop += BranchIfTrue(&loop_repeat, &loop_exit, negate); | |
3659 | |
3660 Fragment repeat(loop_repeat); | |
3661 repeat += Goto(join); | |
3662 | |
3663 loop_depth_dec(); | |
3664 return Fragment(new (Z) GotoInstr(join), loop_exit); | |
3665 } | |
3666 | |
3667 Fragment StreamingFlowGraphBuilder::BuildForStatement() { | |
3668 intptr_t offset = ReaderOffset() - 1; // Include the tag. | |
3669 | |
3670 Fragment declarations; | |
3671 | |
3672 bool new_context = false; | |
3673 declarations += EnterScope(offset, &new_context); | |
3674 | |
3675 intptr_t list_length = ReadListLength(); // read number of variables. | |
3676 for (intptr_t i = 0; i < list_length; ++i) { | |
3677 declarations += BuildVariableDeclaration(false); // read ith variable. | |
3678 } | |
3679 | |
3680 loop_depth_inc(); | |
3681 bool negate = false; | |
3682 Tag tag = ReadTag(); // Read first part of condition. | |
3683 Fragment condition = | |
3684 tag == kNothing ? Constant(Bool::True()) | |
3685 : TranslateCondition(&negate); // read rest of condition. | |
3686 TargetEntryInstr* body_entry; | |
3687 TargetEntryInstr* loop_exit; | |
3688 condition += BranchIfTrue(&body_entry, &loop_exit, negate); | |
3689 | |
3690 Fragment updates; | |
3691 list_length = ReadListLength(); // read number of updates. | |
3692 for (intptr_t i = 0; i < list_length; ++i) { | |
3693 updates += BuildExpression(); // read ith update. | |
3694 updates += Drop(); | |
3695 } | |
3696 | |
3697 Fragment body(body_entry); | |
3698 body += BuildStatement(); // read body. | |
3699 | |
3700 if (body.is_open()) { | |
3701 // We allocated a fresh context before the loop which contains captured | |
3702 // [ForStatement] variables. Before jumping back to the loop entry we clone | |
3703 // the context object (at same depth) which ensures the next iteration of | |
3704 // the body gets a fresh set of [ForStatement] variables (with the old | |
3705 // (possibly updated) values). | |
3706 if (new_context) body += CloneContext(); | |
3707 | |
3708 body += updates; | |
3709 JoinEntryInstr* join = BuildJoinEntry(); | |
3710 declarations += Goto(join); | |
3711 body += Goto(join); | |
3712 | |
3713 Fragment loop(join); | |
3714 loop += CheckStackOverflow(); | |
3715 loop += condition; | |
3716 } else { | |
3717 declarations += condition; | |
3718 } | |
3719 | |
3720 Fragment loop(declarations.entry, loop_exit); | |
3721 loop_depth_dec(); | |
3722 | |
3723 loop += ExitScope(offset); | |
3724 | |
3725 return loop; | |
3726 } | |
3727 | |
3728 Fragment StreamingFlowGraphBuilder::BuildForInStatement(bool async) { | |
3729 intptr_t offset = ReaderOffset() - 1; // Include the tag. | |
3730 | |
3731 TokenPosition position = ReadPosition(); // read position. | |
3732 intptr_t variable_kernel_position = ReaderOffset(); | |
3733 SkipVariableDeclaration(); // read variable. | |
3734 TokenPosition org_direct_descendant_position = direct_descendant_position_; | |
3735 ResetDirectDescendantPosition(); | |
3736 | |
3737 Fragment instructions = BuildExpression(); // read iterable. | |
3738 instructions += PushArgument(); | |
3739 | |
3740 TokenPosition iterable_position = direct_descendant_position_; | |
3741 direct_descendant_position_ = org_direct_descendant_position; | |
3742 | |
3743 const dart::String& iterator_getter = dart::String::ZoneHandle( | |
3744 Z, dart::Field::GetterSymbol(Symbols::Iterator())); | |
3745 instructions += | |
3746 InstanceCall(iterable_position, iterator_getter, Token::kGET, 1); | |
3747 LocalVariable* iterator = scopes()->iterator_variables[for_in_depth()]; | |
3748 instructions += StoreLocal(TokenPosition::kNoSource, iterator); | |
3749 instructions += Drop(); | |
3750 | |
3751 for_in_depth_inc(); | |
3752 loop_depth_inc(); | |
3753 Fragment condition = LoadLocal(iterator); | |
3754 condition += PushArgument(); | |
3755 condition += | |
3756 InstanceCall(iterable_position, Symbols::MoveNext(), Token::kILLEGAL, 1); | |
3757 TargetEntryInstr* body_entry; | |
3758 TargetEntryInstr* loop_exit; | |
3759 condition += BranchIfTrue(&body_entry, &loop_exit, false); | |
3760 | |
3761 Fragment body(body_entry); | |
3762 body += EnterScope(offset); | |
3763 body += LoadLocal(iterator); | |
3764 body += PushArgument(); | |
3765 const dart::String& current_getter = dart::String::ZoneHandle( | |
3766 Z, dart::Field::GetterSymbol(Symbols::Current())); | |
3767 body += InstanceCall(position, current_getter, Token::kGET, 1); | |
3768 body += StoreLocal(TokenPosition::kNoSource, | |
3769 LookupVariable(variable_kernel_position)); | |
3770 body += Drop(); | |
3771 body += BuildStatement(); // read body. | |
3772 body += ExitScope(offset); | |
3773 | |
3774 if (body.is_open()) { | |
3775 JoinEntryInstr* join = BuildJoinEntry(); | |
3776 instructions += Goto(join); | |
3777 body += Goto(join); | |
3778 | |
3779 Fragment loop(join); | |
3780 loop += CheckStackOverflow(); | |
3781 loop += condition; | |
3782 } else { | |
3783 instructions += condition; | |
3784 } | |
3785 | |
3786 loop_depth_dec(); | |
3787 for_in_depth_dec(); | |
3788 return Fragment(instructions.entry, loop_exit); | |
3789 } | |
3790 | |
3791 Fragment StreamingFlowGraphBuilder::BuildSwitchStatement() { | |
3792 // We need the number of cases. So start by getting that, then go back. | |
3793 intptr_t offset = ReaderOffset(); | |
3794 SkipExpression(); // temporarily skip condition | |
3795 int num_cases = ReadListLength(); // read number of cases. | |
3796 SetOffset(offset); | |
3797 | |
3798 SwitchBlock block(flow_graph_builder_, num_cases); | |
3799 | |
3800 // Instead of using a variable we should reuse the expression on the stack, | |
3801 // since it won't be assigned again, we don't need phi nodes. | |
3802 Fragment head_instructions = BuildExpression(); // read condition. | |
3803 head_instructions += | |
3804 StoreLocal(TokenPosition::kNoSource, scopes()->switch_variable); | |
3805 head_instructions += Drop(); | |
3806 | |
3807 num_cases = ReadListLength(); // read number of cases. | |
3808 | |
3809 // Phase 1: Generate bodies and try to find out whether a body will be target | |
3810 // of a jump due to: | |
3811 // * `continue case_label` | |
3812 // * `case e1: case e2: body` | |
3813 Fragment* body_fragments = new Fragment[num_cases]; | |
3814 intptr_t* case_expression_offsets = new intptr_t[num_cases]; | |
3815 bool* case_is_default = new bool[num_cases]; | |
3816 | |
3817 for (intptr_t i = 0; i < num_cases; ++i) { | |
3818 case_expression_offsets[i] = ReaderOffset(); | |
3819 int num_expressions = ReadListLength(); // read number of expressions. | |
3820 for (intptr_t j = 0; j < num_expressions; ++j) { | |
3821 ReadPosition(); // read jth position. | |
3822 SkipExpression(); // read jth expression. | |
3823 } | |
3824 bool is_default = ReadBool(); // read is_default. | |
3825 case_is_default[i] = is_default; | |
3826 Fragment& body_fragment = body_fragments[i] = | |
3827 BuildStatement(); // read body. | |
3828 | |
3829 if (body_fragment.entry == NULL) { | |
3830 // Make a NOP in order to ensure linking works properly. | |
3831 body_fragment = NullConstant(); | |
3832 body_fragment += Drop(); | |
3833 } | |
3834 | |
3835 // The Dart language specification mandates fall-throughs in [SwitchCase]es | |
3836 // to be runtime errors. | |
3837 if (!is_default && body_fragment.is_open() && (i < (num_cases - 1))) { | |
3838 const dart::Class& klass = dart::Class::ZoneHandle( | |
3839 Z, dart::Library::LookupCoreClass(Symbols::FallThroughError())); | |
3840 ASSERT(!klass.IsNull()); | |
3841 const dart::Function& constructor = dart::Function::ZoneHandle( | |
3842 Z, klass.LookupConstructorAllowPrivate( | |
3843 H.DartSymbol("FallThroughError._create"))); | |
3844 ASSERT(!constructor.IsNull()); | |
3845 const dart::String& url = H.DartString( | |
3846 parsed_function()->function().ToLibNamePrefixedQualifiedCString(), | |
3847 Heap::kOld); | |
3848 | |
3849 // Create instance of _FallThroughError | |
3850 body_fragment += AllocateObject(klass, 0); | |
3851 LocalVariable* instance = MakeTemporary(); | |
3852 | |
3853 // Call _FallThroughError._create constructor. | |
3854 body_fragment += LoadLocal(instance); | |
3855 body_fragment += PushArgument(); // this | |
3856 | |
3857 body_fragment += Constant(url); | |
3858 body_fragment += PushArgument(); // url | |
3859 | |
3860 body_fragment += NullConstant(); | |
3861 body_fragment += PushArgument(); // line | |
3862 | |
3863 body_fragment += StaticCall(TokenPosition::kNoSource, constructor, 3); | |
3864 body_fragment += Drop(); | |
3865 | |
3866 // Throw the exception | |
3867 body_fragment += PushArgument(); | |
3868 body_fragment += ThrowException(TokenPosition::kNoSource); | |
3869 body_fragment += Drop(); | |
3870 } | |
3871 | |
3872 // If there is an implicit fall-through we have one [SwitchCase] and | |
3873 // multiple expressions, e.g. | |
3874 // | |
3875 // switch(expr) { | |
3876 // case a: | |
3877 // case b: | |
3878 // <stmt-body> | |
3879 // } | |
3880 // | |
3881 // This means that the <stmt-body> will have more than 1 incoming edge (one | |
3882 // from `a == expr` and one from `a != expr && b == expr`). The | |
3883 // `block.Destination()` records the additional jump. | |
3884 if (num_expressions > 1) { | |
3885 block.DestinationDirect(i); | |
3886 } | |
3887 } | |
3888 | |
3889 intptr_t end_offset = ReaderOffset(); | |
3890 | |
3891 // Phase 2: Generate everything except the real bodies: | |
3892 // * jump directly to a body (if there is no jumper) | |
3893 // * jump to a wrapper block which jumps to the body (if there is a jumper) | |
3894 Fragment current_instructions = head_instructions; | |
3895 for (intptr_t i = 0; i < num_cases; ++i) { | |
3896 SetOffset(case_expression_offsets[i]); | |
3897 int num_expressions = ReadListLength(); // read length of expressions. | |
3898 | |
3899 if (case_is_default[i]) { | |
3900 ASSERT(i == (num_cases - 1)); | |
3901 | |
3902 // Evaluate the conditions for the default [SwitchCase] just for the | |
3903 // purpose of potentially triggering a compile-time error. | |
3904 | |
3905 for (intptr_t j = 0; j < num_expressions; ++j) { | |
3906 ReadPosition(); // read jth position. | |
3907 // this reads the expression, but doesn't skip past it. | |
3908 constant_evaluator_.EvaluateExpression(ReaderOffset()); | |
3909 SkipExpression(); // read jth expression. | |
3910 } | |
3911 | |
3912 if (block.HadJumper(i)) { | |
3913 // There are several branches to the body, so we will make a goto to | |
3914 // the join block (and prepend a join instruction to the real body). | |
3915 JoinEntryInstr* join = block.DestinationDirect(i); | |
3916 current_instructions += Goto(join); | |
3917 | |
3918 current_instructions = Fragment(current_instructions.entry, join); | |
3919 current_instructions += body_fragments[i]; | |
3920 } else { | |
3921 current_instructions += body_fragments[i]; | |
3922 } | |
3923 } else { | |
3924 JoinEntryInstr* body_join = NULL; | |
3925 if (block.HadJumper(i)) { | |
3926 body_join = block.DestinationDirect(i); | |
3927 body_fragments[i] = Fragment(body_join) + body_fragments[i]; | |
3928 } | |
3929 | |
3930 for (intptr_t j = 0; j < num_expressions; ++j) { | |
3931 TargetEntryInstr* then; | |
3932 TargetEntryInstr* otherwise; | |
3933 | |
3934 TokenPosition position = ReadPosition(); // read jth position. | |
3935 current_instructions += | |
3936 Constant(constant_evaluator_.EvaluateExpression(ReaderOffset())); | |
3937 SkipExpression(); // read jth expression. | |
3938 current_instructions += PushArgument(); | |
3939 current_instructions += LoadLocal(scopes()->switch_variable); | |
3940 current_instructions += PushArgument(); | |
3941 current_instructions += | |
3942 InstanceCall(position, Symbols::EqualOperator(), Token::kEQ, | |
3943 /*argument_count=*/2, | |
3944 /*num_args_checked=*/2); | |
3945 current_instructions += BranchIfTrue(&then, &otherwise, false); | |
3946 | |
3947 Fragment then_fragment(then); | |
3948 | |
3949 if (body_join != NULL) { | |
3950 // There are several branches to the body, so we will make a goto to | |
3951 // the join block (the real body has already been prepended with a | |
3952 // join instruction). | |
3953 then_fragment += Goto(body_join); | |
3954 } else { | |
3955 // There is only a signle branch to the body, so we will just append | |
3956 // the body fragment. | |
3957 then_fragment += body_fragments[i]; | |
3958 } | |
3959 | |
3960 current_instructions = Fragment(otherwise); | |
3961 } | |
3962 } | |
3963 } | |
3964 | |
3965 bool has_no_default = num_cases > 0 && !case_is_default[num_cases - 1]; | |
3966 if (has_no_default) { | |
3967 // There is no default, which means we have an open [current_instructions] | |
3968 // (which is a [TargetEntryInstruction] for the last "otherwise" branch). | |
3969 // | |
3970 // Furthermore the last [SwitchCase] can be open as well. If so, we need | |
3971 // to join these two. | |
3972 Fragment& last_body = body_fragments[num_cases - 1]; | |
3973 if (last_body.is_open()) { | |
3974 ASSERT(current_instructions.is_open()); | |
3975 ASSERT(current_instructions.current->IsTargetEntry()); | |
3976 | |
3977 // Join the last "otherwise" branch and the last [SwitchCase] fragment. | |
3978 JoinEntryInstr* join = BuildJoinEntry(); | |
3979 current_instructions += Goto(join); | |
3980 last_body += Goto(join); | |
3981 | |
3982 current_instructions = Fragment(join); | |
3983 } | |
3984 } else { | |
3985 // All non-default cases will be closed (i.e. break/continue/throw/return) | |
3986 // So it is fine to just let more statements after the switch append to the | |
3987 // default case. | |
3988 } | |
3989 | |
3990 delete[] body_fragments; | |
3991 | |
3992 SetOffset(end_offset); | |
3993 return Fragment(head_instructions.entry, current_instructions.current); | |
3994 } | |
3995 | |
3996 Fragment StreamingFlowGraphBuilder::BuildContinueSwitchStatement() { | |
3997 intptr_t target_index = ReadUInt(); // read target index. | |
3998 | |
3999 TryFinallyBlock* outer_finally = NULL; | |
4000 intptr_t target_context_depth = -1; | |
4001 JoinEntryInstr* entry = switch_block()->Destination( | |
4002 target_index, &outer_finally, &target_context_depth); | |
4003 | |
4004 Fragment instructions; | |
4005 instructions += | |
4006 TranslateFinallyFinalizers(outer_finally, target_context_depth); | |
4007 if (instructions.is_open()) { | |
4008 instructions += Goto(entry); | |
4009 } | |
4010 return instructions; | |
4011 } | |
4012 | |
4013 Fragment StreamingFlowGraphBuilder::BuildIfStatement() { | |
4014 bool negate; | |
4015 Fragment instructions = TranslateCondition(&negate); // read condition. | |
4016 TargetEntryInstr* then_entry; | |
4017 TargetEntryInstr* otherwise_entry; | |
4018 instructions += BranchIfTrue(&then_entry, &otherwise_entry, negate); | |
4019 | |
4020 Fragment then_fragment(then_entry); | |
4021 then_fragment += BuildStatement(); // read then. | |
4022 | |
4023 Fragment otherwise_fragment(otherwise_entry); | |
4024 otherwise_fragment += BuildStatement(); // read otherwise. | |
4025 | |
4026 if (then_fragment.is_open()) { | |
4027 if (otherwise_fragment.is_open()) { | |
4028 JoinEntryInstr* join = BuildJoinEntry(); | |
4029 then_fragment += Goto(join); | |
4030 otherwise_fragment += Goto(join); | |
4031 return Fragment(instructions.entry, join); | |
4032 } else { | |
4033 return Fragment(instructions.entry, then_fragment.current); | |
4034 } | |
4035 } else if (otherwise_fragment.is_open()) { | |
4036 return Fragment(instructions.entry, otherwise_fragment.current); | |
4037 } else { | |
4038 return instructions.closed(); | |
4039 } | |
4040 } | |
4041 | |
4042 Fragment StreamingFlowGraphBuilder::BuildReturnStatement() { | |
4043 TokenPosition position = ReadPosition(); // read position. | |
4044 Tag tag = ReadTag(); // read first part of expression. | |
4045 | |
4046 bool inside_try_finally = try_finally_block() != NULL; | |
4047 | |
4048 Fragment instructions = tag == kNothing | |
4049 ? NullConstant() | |
4050 : BuildExpression(); // read rest of expression. | |
4051 | |
4052 if (instructions.is_open()) { | |
4053 if (inside_try_finally) { | |
4054 ASSERT(scopes()->finally_return_variable != NULL); | |
4055 const Function& function = parsed_function()->function(); | |
4056 if (NeedsDebugStepCheck(function, position)) { | |
4057 instructions += DebugStepCheck(position); | |
4058 } | |
4059 instructions += StoreLocal(position, scopes()->finally_return_variable); | |
4060 instructions += Drop(); | |
4061 instructions += TranslateFinallyFinalizers(NULL, -1); | |
4062 if (instructions.is_open()) { | |
4063 instructions += LoadLocal(scopes()->finally_return_variable); | |
4064 instructions += Return(TokenPosition::kNoSource); | |
4065 } | |
4066 } else { | |
4067 instructions += Return(position); | |
4068 } | |
4069 } else { | |
4070 Pop(); | |
4071 } | |
4072 | |
4073 return instructions; | |
4074 } | |
4075 | |
4076 Fragment StreamingFlowGraphBuilder::BuildTryCatch() { | |
4077 InlineBailout("kernel::FlowgraphBuilder::VisitTryCatch"); | |
4078 | |
4079 intptr_t try_handler_index = AllocateTryIndex(); | |
4080 Fragment try_body = TryCatch(try_handler_index); | |
4081 JoinEntryInstr* after_try = BuildJoinEntry(); | |
4082 | |
4083 // Fill in the body of the try. | |
4084 try_depth_inc(); | |
4085 { | |
4086 TryCatchBlock block(flow_graph_builder_, try_handler_index); | |
4087 try_body += BuildStatement(); // read body. | |
4088 try_body += Goto(after_try); | |
4089 } | |
4090 try_depth_dec(); | |
4091 | |
4092 bool needs_stacktrace = ReadBool(); // read any_catch_needs_stack_trace | |
4093 | |
4094 catch_depth_inc(); | |
4095 intptr_t num_matches = ReadListLength(); // read number of catches. | |
4096 const Array& handler_types = | |
4097 Array::ZoneHandle(Z, Array::New(num_matches, Heap::kOld)); | |
4098 Fragment catch_body = | |
4099 CatchBlockEntry(handler_types, try_handler_index, needs_stacktrace); | |
4100 // Fill in the body of the catch. | |
4101 for (intptr_t i = 0; i < num_matches; ++i) { | |
4102 intptr_t catch_offset = ReaderOffset(); // Catch has no tag. | |
4103 Tag tag = PeekTag(); // peek guard type. | |
4104 AbstractType* type_guard = NULL; | |
4105 if (tag != kDynamicType) { | |
4106 type_guard = &T.BuildType(); // read guard. | |
4107 handler_types.SetAt(i, *type_guard); | |
4108 } else { | |
4109 SkipDartType(); // read guard. | |
4110 handler_types.SetAt(i, Object::dynamic_type()); | |
4111 } | |
4112 | |
4113 Fragment catch_handler_body = EnterScope(catch_offset); | |
4114 | |
4115 tag = ReadTag(); // read first part of exception. | |
4116 if (tag == kSomething) { | |
4117 catch_handler_body += LoadLocal(CurrentException()); | |
4118 catch_handler_body += | |
4119 StoreLocal(TokenPosition::kNoSource, LookupVariable(ReaderOffset())); | |
4120 catch_handler_body += Drop(); | |
4121 SkipVariableDeclaration(); // read exception. | |
4122 } | |
4123 | |
4124 tag = ReadTag(); // read first part of stack trace. | |
4125 if (tag == kSomething) { | |
4126 catch_handler_body += LoadLocal(CurrentStackTrace()); | |
4127 catch_handler_body += | |
4128 StoreLocal(TokenPosition::kNoSource, LookupVariable(ReaderOffset())); | |
4129 catch_handler_body += Drop(); | |
4130 SkipVariableDeclaration(); // read stack trace. | |
4131 } | |
4132 | |
4133 { | |
4134 CatchBlock block(flow_graph_builder_, CurrentException(), | |
4135 CurrentStackTrace(), try_handler_index); | |
4136 | |
4137 catch_handler_body += BuildStatement(); // read body. | |
4138 | |
4139 // Note: ExitScope adjusts context_depth_ so even if catch_handler_body | |
4140 // is closed we still need to execute ExitScope for its side effect. | |
4141 catch_handler_body += ExitScope(catch_offset); | |
4142 if (catch_handler_body.is_open()) { | |
4143 catch_handler_body += Goto(after_try); | |
4144 } | |
4145 } | |
4146 | |
4147 if (type_guard != NULL) { | |
4148 if (type_guard->IsMalformed()) { | |
4149 catch_body += ThrowTypeError(); | |
4150 catch_body += Drop(); | |
4151 } else { | |
4152 catch_body += LoadLocal(CurrentException()); | |
4153 catch_body += PushArgument(); // exception | |
4154 catch_body += NullConstant(); | |
4155 catch_body += PushArgument(); // instantiator type arguments | |
4156 catch_body += NullConstant(); | |
4157 catch_body += PushArgument(); // function type arguments | |
4158 catch_body += Constant(*type_guard); | |
4159 catch_body += PushArgument(); // guard type | |
4160 catch_body += InstanceCall( | |
4161 TokenPosition::kNoSource, | |
4162 dart::Library::PrivateCoreLibName(Symbols::_instanceOf()), | |
4163 Token::kIS, 4); | |
4164 | |
4165 TargetEntryInstr* catch_entry; | |
4166 TargetEntryInstr* next_catch_entry; | |
4167 catch_body += BranchIfTrue(&catch_entry, &next_catch_entry, false); | |
4168 | |
4169 Fragment(catch_entry) + catch_handler_body; | |
4170 catch_body = Fragment(next_catch_entry); | |
4171 } | |
4172 } else { | |
4173 catch_body += catch_handler_body; | |
4174 } | |
4175 } | |
4176 | |
4177 // In case the last catch body was not handling the exception and branching to | |
4178 // after the try block, we will rethrow the exception (i.e. no default catch | |
4179 // handler). | |
4180 if (catch_body.is_open()) { | |
4181 catch_body += LoadLocal(CurrentException()); | |
4182 catch_body += PushArgument(); | |
4183 catch_body += LoadLocal(CurrentStackTrace()); | |
4184 catch_body += PushArgument(); | |
4185 catch_body += RethrowException(TokenPosition::kNoSource, try_handler_index); | |
4186 Drop(); | |
4187 } | |
4188 catch_depth_dec(); | |
4189 | |
4190 return Fragment(try_body.entry, after_try); | |
4191 } | |
4192 | |
4193 Fragment StreamingFlowGraphBuilder::BuildTryFinally() { | |
4194 // Note on streaming: | |
4195 // We only stream this TryFinally if we can stream everything inside it, | |
4196 // so creating a "TryFinallyBlock" with a kernel binary offset instead of an | |
4197 // AST node isn't a problem. | |
4198 | |
4199 | |
4200 InlineBailout("kernel::FlowgraphBuilder::VisitTryFinally"); | |
4201 | |
4202 // There are 5 different cases where we need to execute the finally block: | |
4203 // | |
4204 // a) 1/2/3th case: Special control flow going out of `node->body()`: | |
4205 // | |
4206 // * [BreakStatement] transfers control to a [LabledStatement] | |
4207 // * [ContinueSwitchStatement] transfers control to a [SwitchCase] | |
4208 // * [ReturnStatement] returns a value | |
4209 // | |
4210 // => All three cases will automatically append all finally blocks | |
4211 // between the branching point and the destination (so we don't need to | |
4212 // do anything here). | |
4213 // | |
4214 // b) 4th case: Translating the body resulted in an open fragment (i.e. body | |
4215 // executes without any control flow out of it) | |
4216 // | |
4217 // => We are responsible for jumping out of the body to a new block (with | |
4218 // different try index) and execute the finalizer. | |
4219 // | |
4220 // c) 5th case: An exception occurred inside the body. | |
4221 // | |
4222 // => We are responsible for catching it, executing the finally block and | |
4223 // rethrowing the exception. | |
4224 intptr_t try_handler_index = AllocateTryIndex(); | |
4225 Fragment try_body = TryCatch(try_handler_index); | |
4226 JoinEntryInstr* after_try = BuildJoinEntry(); | |
4227 | |
4228 intptr_t offset = ReaderOffset(); | |
4229 SkipStatement(); // temporarily read body. | |
4230 intptr_t finalizer_offset = ReaderOffset(); | |
4231 SetOffset(offset); | |
4232 | |
4233 // Fill in the body of the try. | |
4234 try_depth_inc(); | |
4235 { | |
4236 TryFinallyBlock tfb(flow_graph_builder_, NULL, finalizer_offset); | |
4237 TryCatchBlock tcb(flow_graph_builder_, try_handler_index); | |
4238 try_body += BuildStatement(); // read body. | |
4239 } | |
4240 try_depth_dec(); | |
4241 | |
4242 if (try_body.is_open()) { | |
4243 // Please note: The try index will be on level out of this block, | |
4244 // thereby ensuring if there's an exception in the finally block we | |
4245 // won't run it twice. | |
4246 JoinEntryInstr* finally_entry = BuildJoinEntry(); | |
4247 | |
4248 try_body += Goto(finally_entry); | |
4249 | |
4250 Fragment finally_body(finally_entry); | |
4251 finally_body += BuildStatement(); // read finalizer. | |
4252 finally_body += Goto(after_try); | |
4253 } | |
4254 | |
4255 // Fill in the body of the catch. | |
4256 catch_depth_inc(); | |
4257 const Array& handler_types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld)); | |
4258 handler_types.SetAt(0, Object::dynamic_type()); | |
4259 // Note: rethrow will actually force mark the handler as needing a stacktrace. | |
4260 Fragment finally_body = CatchBlockEntry(handler_types, try_handler_index, | |
4261 /* needs_stacktrace = */ false); | |
4262 SetOffset(finalizer_offset); | |
4263 finally_body += BuildStatement(); // read finalizer | |
4264 if (finally_body.is_open()) { | |
4265 finally_body += LoadLocal(CurrentException()); | |
4266 finally_body += PushArgument(); | |
4267 finally_body += LoadLocal(CurrentStackTrace()); | |
4268 finally_body += PushArgument(); | |
4269 finally_body += | |
4270 RethrowException(TokenPosition::kNoSource, try_handler_index); | |
4271 Drop(); | |
4272 } | |
4273 catch_depth_dec(); | |
4274 | |
4275 return Fragment(try_body.entry, after_try); | |
4276 } | |
4277 | |
4278 Fragment StreamingFlowGraphBuilder::BuildYieldStatement() { | |
4279 TokenPosition position = ReadPosition(); // read position. | |
4280 uint8_t flags = ReadByte(); // read flags. | |
4281 | |
4282 ASSERT((flags & kFlagNative) == kFlagNative); // Must have been desugared. | |
4283 | |
4284 // Setup yield/continue point: | |
4285 // | |
4286 // ... | |
4287 // :await_jump_var = index; | |
4288 // :await_ctx_var = :current_context_var | |
4289 // return <expr> | |
4290 // | |
4291 // Continuation<index>: | |
4292 // Drop(1) | |
4293 // ... | |
4294 // | |
4295 // BuildGraphOfFunction will create a dispatch that jumps to | |
4296 // Continuation<:await_jump_var> upon entry to the function. | |
4297 // | |
4298 Fragment instructions = IntConstant(yield_continuations().length() + 1); | |
4299 instructions += | |
4300 StoreLocal(TokenPosition::kNoSource, scopes()->yield_jump_variable); | |
4301 instructions += Drop(); | |
4302 instructions += LoadLocal(parsed_function()->current_context_var()); | |
4303 instructions += | |
4304 StoreLocal(TokenPosition::kNoSource, scopes()->yield_context_variable); | |
4305 instructions += Drop(); | |
4306 instructions += BuildExpression(); // read expression. | |
4307 instructions += Return(TokenPosition::kNoSource); | |
4308 | |
4309 // Note: DropTempsInstr serves as an anchor instruction. It will not | |
4310 // be linked into the resulting graph. | |
4311 DropTempsInstr* anchor = new (Z) DropTempsInstr(0, NULL); | |
4312 yield_continuations().Add(YieldContinuation(anchor, CurrentTryIndex())); | |
4313 | |
4314 Fragment continuation(instructions.entry, anchor); | |
4315 | |
4316 if (parsed_function()->function().IsAsyncClosure() || | |
4317 parsed_function()->function().IsAsyncGenClosure()) { | |
4318 // If function is async closure or async gen closure it takes three | |
4319 // parameters where the second and the third are exception and stack_trace. | |
4320 // Check if exception is non-null and rethrow it. | |
4321 // | |
4322 // :async_op([:result, :exception, :stack_trace]) { | |
4323 // ... | |
4324 // Continuation<index>: | |
4325 // if (:exception != null) rethrow(:exception, :stack_trace); | |
4326 // ... | |
4327 // } | |
4328 // | |
4329 LocalScope* scope = parsed_function()->node_sequence()->scope(); | |
4330 LocalVariable* exception_var = scope->VariableAt(2); | |
4331 LocalVariable* stack_trace_var = scope->VariableAt(3); | |
4332 ASSERT(exception_var->name().raw() == Symbols::ExceptionParameter().raw()); | |
4333 ASSERT(stack_trace_var->name().raw() == | |
4334 Symbols::StackTraceParameter().raw()); | |
4335 | |
4336 TargetEntryInstr* no_error; | |
4337 TargetEntryInstr* error; | |
4338 | |
4339 continuation += LoadLocal(exception_var); | |
4340 continuation += BranchIfNull(&no_error, &error); | |
4341 | |
4342 Fragment rethrow(error); | |
4343 rethrow += LoadLocal(exception_var); | |
4344 rethrow += PushArgument(); | |
4345 rethrow += LoadLocal(stack_trace_var); | |
4346 rethrow += PushArgument(); | |
4347 rethrow += RethrowException(position, CatchClauseNode::kInvalidTryIndex); | |
4348 Drop(); | |
4349 | |
4350 | |
4351 continuation = Fragment(continuation.entry, no_error); | |
4352 } | |
4353 | |
4354 return continuation; | |
4355 } | |
4356 | |
4357 Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration(bool has_tag) { | |
4358 intptr_t kernel_position = ReaderOffset() - (has_tag ? 1 : 0); | |
4359 LocalVariable* variable = LookupVariable(kernel_position); | |
4360 | |
4361 TokenPosition position = ReadPosition(); // read position. | |
4362 TokenPosition equals_position = ReadPosition(); // read equals position. | |
4363 word flags = ReadFlags(); // read flags. | |
4364 dart::String& name = H.DartSymbol(ReadUInt()); // read name index. | |
4365 AbstractType& type = T.BuildType(); // read type. | |
4366 Tag tag = ReadTag(); // read (first part of) initializer. | |
4367 | |
4368 Fragment instructions; | |
4369 if (tag == kNothing) { | |
4370 instructions += NullConstant(); | |
4371 } else { | |
4372 if ((flags & kFlagConst) == kFlagConst) { | |
4373 // Const! | |
4374 const Instance& constant_value = constant_evaluator_.EvaluateExpression( | |
4375 ReaderOffset()); // read initializer form current position. | |
4376 variable->SetConstValue(constant_value); | |
4377 instructions += Constant(constant_value); | |
4378 SkipExpression(); // skip initializer. | |
4379 } else { | |
4380 // Initializer | |
4381 instructions += BuildExpression(); // read (actual) initializer. | |
4382 instructions += CheckVariableTypeInCheckedMode(type, name); | |
4383 } | |
4384 } | |
4385 | |
4386 // Use position of equal sign if it exists. If the equal sign does not exist | |
4387 // use the position of the identifier. | |
4388 TokenPosition debug_position = Utils::Maximum(position, equals_position); | |
4389 if (NeedsDebugStepCheck(stack(), debug_position)) { | |
4390 instructions = DebugStepCheck(debug_position) + instructions; | |
4391 } | |
4392 instructions += StoreLocal(position, variable); | |
4393 instructions += Drop(); | |
4394 return instructions; | |
4395 } | |
603 | 4396 |
604 } // namespace kernel | 4397 } // namespace kernel |
605 } // namespace dart | 4398 } // namespace dart |
606 | 4399 |
607 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 4400 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
OLD | NEW |