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