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

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

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

Powered by Google App Engine
This is Rietveld 408576698