Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(153)

Side by Side Diff: runtime/vm/kernel_binary_flowgraph.cc

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

Powered by Google App Engine
This is Rietveld 408576698