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