| 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/object_store.h" | 7 #include "vm/object_store.h" |
| 8 | 8 |
| 9 #if !defined(DART_PRECOMPILED_RUNTIME) | 9 #if !defined(DART_PRECOMPILED_RUNTIME) |
| 10 | 10 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 : builder_->parsed_function()->function().script())), | 31 : builder_->parsed_function()->function().script())), |
| 32 result_(Instance::Handle(zone)) {} | 32 result_(Instance::Handle(zone)) {} |
| 33 | 33 |
| 34 | 34 |
| 35 Instance& StreamingConstantEvaluator::EvaluateExpression() { | 35 Instance& StreamingConstantEvaluator::EvaluateExpression() { |
| 36 intptr_t offset = builder_->ReaderOffset(); | 36 intptr_t offset = builder_->ReaderOffset(); |
| 37 if (!GetCachedConstant(offset, &result_)) { | 37 if (!GetCachedConstant(offset, &result_)) { |
| 38 uint8_t payload = 0; | 38 uint8_t payload = 0; |
| 39 Tag tag = builder_->ReadTag(&payload); | 39 Tag tag = builder_->ReadTag(&payload); |
| 40 switch (tag) { | 40 switch (tag) { |
| 41 case kStaticGet: |
| 42 EvaluateStaticGet(); |
| 43 break; |
| 41 case kSymbolLiteral: | 44 case kSymbolLiteral: |
| 42 EvaluateSymbolLiteral(); | 45 EvaluateSymbolLiteral(); |
| 43 break; | 46 break; |
| 44 case kDoubleLiteral: | 47 case kDoubleLiteral: |
| 45 EvaluateDoubleLiteral(); | 48 EvaluateDoubleLiteral(); |
| 46 break; | 49 break; |
| 47 default: | 50 default: |
| 48 UNREACHABLE(); | 51 UNREACHABLE(); |
| 49 } | 52 } |
| 50 | 53 |
| 51 CacheConstantValue(offset, result_); | 54 CacheConstantValue(offset, result_); |
| 52 } | 55 } |
| 53 // We return a new `ZoneHandle` here on purpose: The intermediate language | 56 // We return a new `ZoneHandle` here on purpose: The intermediate language |
| 54 // instructions do not make a copy of the handle, so we do it. | 57 // instructions do not make a copy of the handle, so we do it. |
| 55 return dart::Instance::ZoneHandle(Z, result_.raw()); | 58 return dart::Instance::ZoneHandle(Z, result_.raw()); |
| 56 } | 59 } |
| 57 | 60 |
| 61 void StreamingConstantEvaluator::EvaluateStaticGet() { |
| 62 builder_->ReadPosition(); |
| 63 int canonical_name_index = builder_->ReadUInt(); |
| 64 CanonicalName* target = builder_->GetCanonicalName(canonical_name_index); |
| 65 |
| 66 if (target->IsField()) { |
| 67 const dart::Field& field = |
| 68 dart::Field::Handle(Z, H.LookupFieldByKernelField(target)); |
| 69 if (field.StaticValue() == Object::sentinel().raw() || |
| 70 field.StaticValue() == Object::transition_sentinel().raw()) { |
| 71 field.EvaluateInitializer(); |
| 72 result_ = field.StaticValue(); |
| 73 result_ = H.Canonicalize(result_); |
| 74 field.SetStaticValue(result_, true); |
| 75 } else { |
| 76 result_ = field.StaticValue(); |
| 77 } |
| 78 } else if (target->IsProcedure()) { |
| 79 const Function& function = |
| 80 Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target)); |
| 81 |
| 82 if (target->IsMethod()) { |
| 83 Function& closure_function = |
| 84 Function::ZoneHandle(Z, function.ImplicitClosureFunction()); |
| 85 closure_function.set_kernel_function(function.kernel_function()); |
| 86 result_ = closure_function.ImplicitStaticClosure(); |
| 87 result_ = H.Canonicalize(result_); |
| 88 } else if (target->IsGetter()) { |
| 89 UNIMPLEMENTED(); |
| 90 } else { |
| 91 UNIMPLEMENTED(); |
| 92 } |
| 93 } |
| 94 } |
| 95 |
| 58 void StreamingConstantEvaluator::EvaluateSymbolLiteral() { | 96 void StreamingConstantEvaluator::EvaluateSymbolLiteral() { |
| 59 int str_index = builder_->ReadUInt(); | 97 int str_index = builder_->ReadUInt(); |
| 60 const dart::String& symbol_value = builder_->DartSymbol(str_index); | 98 const dart::String& symbol_value = builder_->DartSymbol(str_index); |
| 61 | 99 |
| 62 const dart::Class& symbol_class = | 100 const dart::Class& symbol_class = |
| 63 dart::Class::ZoneHandle(Z, I->object_store()->symbol_class()); | 101 dart::Class::ZoneHandle(Z, I->object_store()->symbol_class()); |
| 64 ASSERT(!symbol_class.IsNull()); | 102 ASSERT(!symbol_class.IsNull()); |
| 65 const dart::Function& symbol_constructor = Function::ZoneHandle( | 103 const dart::Function& symbol_constructor = Function::ZoneHandle( |
| 66 Z, symbol_class.LookupConstructor(Symbols::SymbolCtor())); | 104 Z, symbol_class.LookupConstructor(Symbols::SymbolCtor())); |
| 67 ASSERT(!symbol_constructor.IsNull()); | 105 ASSERT(!symbol_constructor.IsNull()); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 // case kSpecializedVariableSet: | 223 // case kSpecializedVariableSet: |
| 186 // return VariableSet::ReadFrom(reader_, payload); | 224 // return VariableSet::ReadFrom(reader_, payload); |
| 187 // case kPropertyGet: | 225 // case kPropertyGet: |
| 188 // return PropertyGet::ReadFrom(reader_); | 226 // return PropertyGet::ReadFrom(reader_); |
| 189 // case kPropertySet: | 227 // case kPropertySet: |
| 190 // return PropertySet::ReadFrom(reader_); | 228 // return PropertySet::ReadFrom(reader_); |
| 191 // case kDirectPropertyGet: | 229 // case kDirectPropertyGet: |
| 192 // return DirectPropertyGet::ReadFrom(reader_); | 230 // return DirectPropertyGet::ReadFrom(reader_); |
| 193 // case kDirectPropertySet: | 231 // case kDirectPropertySet: |
| 194 // return DirectPropertySet::ReadFrom(reader_); | 232 // return DirectPropertySet::ReadFrom(reader_); |
| 195 // case kStaticGet: | 233 case kStaticGet: |
| 196 // return StaticGet::ReadFrom(reader_); | 234 return BuildStaticGet(); |
| 197 // case kStaticSet: | 235 // case kStaticSet: |
| 198 // return StaticSet::ReadFrom(reader_); | 236 // return StaticSet::ReadFrom(reader_); |
| 199 // case kMethodInvocation: | 237 // case kMethodInvocation: |
| 200 // return MethodInvocation::ReadFrom(reader_); | 238 // return MethodInvocation::ReadFrom(reader_); |
| 201 // case kDirectMethodInvocation: | 239 // case kDirectMethodInvocation: |
| 202 // return DirectMethodInvocation::ReadFrom(reader_); | 240 // return DirectMethodInvocation::ReadFrom(reader_); |
| 203 // case kStaticInvocation: | 241 // case kStaticInvocation: |
| 204 // return StaticInvocation::ReadFrom(reader_, false); | 242 // return StaticInvocation::ReadFrom(reader_, false); |
| 205 // case kConstStaticInvocation: | 243 // case kConstStaticInvocation: |
| 206 // return StaticInvocation::ReadFrom(reader_, true); | 244 // return StaticInvocation::ReadFrom(reader_, true); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 UNREACHABLE(); | 304 UNREACHABLE(); |
| 267 } | 305 } |
| 268 | 306 |
| 269 return Fragment(); | 307 return Fragment(); |
| 270 } | 308 } |
| 271 | 309 |
| 272 intptr_t StreamingFlowGraphBuilder::GetStringTableOffset(intptr_t index) { | 310 intptr_t StreamingFlowGraphBuilder::GetStringTableOffset(intptr_t index) { |
| 273 if (string_table_offsets_ != NULL && string_table_entries_read_ > index) { | 311 if (string_table_offsets_ != NULL && string_table_entries_read_ > index) { |
| 274 return string_table_offsets_[index]; | 312 return string_table_offsets_[index]; |
| 275 } | 313 } |
| 314 |
| 315 intptr_t saved_offset = ReaderOffset(); |
| 276 if (string_table_offsets_ == NULL) { | 316 if (string_table_offsets_ == NULL) { |
| 277 reader_->set_offset(4); // Skip kMagicProgramFile - now at string table. | 317 reader_->set_offset(4); // Skip kMagicProgramFile - now at string table. |
| 278 string_table_size_ = ReadListLength(); | 318 string_table_size_ = ReadListLength(); |
| 279 string_table_offsets_ = new intptr_t[string_table_size_]; | 319 string_table_offsets_ = new intptr_t[string_table_size_]; |
| 280 string_table_offsets_[0] = ReaderOffset(); | 320 string_table_offsets_[0] = ReaderOffset(); |
| 281 string_table_entries_read_ = 1; | 321 string_table_entries_read_ = 1; |
| 282 } | 322 } |
| 283 | 323 |
| 284 ASSERT(string_table_size_ > index); | 324 ASSERT(string_table_size_ > index); |
| 285 --string_table_entries_read_; | 325 --string_table_entries_read_; |
| 286 reader_->set_offset(string_table_offsets_[string_table_entries_read_]); | 326 reader_->set_offset(string_table_offsets_[string_table_entries_read_]); |
| 287 for (; string_table_entries_read_ < index; ++string_table_entries_read_) { | 327 for (; string_table_entries_read_ < index; ++string_table_entries_read_) { |
| 288 string_table_offsets_[string_table_entries_read_] = ReaderOffset(); | 328 string_table_offsets_[string_table_entries_read_] = ReaderOffset(); |
| 289 uint32_t bytes = ReadUInt(); | 329 uint32_t bytes = ReadUInt(); |
| 290 SkipBytes(bytes); | 330 SkipBytes(bytes); |
| 291 } | 331 } |
| 292 string_table_offsets_[string_table_entries_read_] = ReaderOffset(); | 332 string_table_offsets_[string_table_entries_read_] = ReaderOffset(); |
| 293 ++string_table_entries_read_; | 333 ++string_table_entries_read_; |
| 294 | 334 |
| 335 SetOffset(saved_offset); |
| 295 return string_table_offsets_[index]; | 336 return string_table_offsets_[index]; |
| 296 } | 337 } |
| 297 | 338 |
| 339 CanonicalName* StreamingFlowGraphBuilder::GetCanonicalName(intptr_t index) { |
| 340 if (index == 0) return NULL; |
| 341 --index; |
| 342 |
| 343 if (canonical_names_ != NULL && canonical_names_entries_read_ > index) { |
| 344 return canonical_names_[index]; |
| 345 } |
| 346 |
| 347 intptr_t saved_offset = ReaderOffset(); |
| 348 if (canonical_names_ == NULL) { |
| 349 // Find offset from where to read canonical names table. |
| 350 |
| 351 // First skip the string table: |
| 352 // Get first string to make sure we have the table size, get last string and |
| 353 // read it to get past the string table. |
| 354 // Note that this will also cache all string positions. |
| 355 GetStringTableOffset(0); |
| 356 SetOffset(GetStringTableOffset(string_table_size_ - 1)); |
| 357 uint32_t bytes = ReadUInt(); |
| 358 SkipBytes(bytes); |
| 359 |
| 360 // Another string table (source URIs) |
| 361 intptr_t list_length = ReadListLength(); |
| 362 for (intptr_t i = 0; i < list_length; ++i) { |
| 363 uint32_t bytes = ReadUInt(); |
| 364 SkipBytes(bytes); |
| 365 } |
| 366 |
| 367 // Source code table |
| 368 for (intptr_t i = 0; i < list_length; ++i) { |
| 369 // Source code |
| 370 intptr_t bytes = ReadUInt(); |
| 371 SkipBytes(bytes); |
| 372 |
| 373 // Line starts table |
| 374 intptr_t line_count = ReadUInt(); |
| 375 for (intptr_t j = 0; j < line_count; ++j) { |
| 376 ReadUInt(); |
| 377 } |
| 378 } |
| 379 |
| 380 // Now at canonical names table. |
| 381 canonical_names_size_ = ReadUInt(); |
| 382 canonical_names_ = new CanonicalName*[canonical_names_size_]; |
| 383 canonical_names_next_offset_ = ReaderOffset(); |
| 384 } |
| 385 |
| 386 SetOffset(canonical_names_next_offset_); |
| 387 for (; canonical_names_entries_read_ <= index; |
| 388 ++canonical_names_entries_read_) { |
| 389 intptr_t biased_parent_index = ReadUInt(); |
| 390 CanonicalName* parent; |
| 391 if (biased_parent_index != 0) { |
| 392 parent = canonical_names_[biased_parent_index - 1]; |
| 393 } else { |
| 394 if (canonical_names_entries_read_ == 0) { |
| 395 parent = CanonicalName::NewRoot(); |
| 396 } else { |
| 397 parent = canonical_names_[0]->parent(); |
| 398 } |
| 399 } |
| 400 ASSERT(parent != NULL); |
| 401 intptr_t name_index = ReadUInt(); |
| 402 String* name = KernelString(name_index); |
| 403 CanonicalName* canonical_name = parent->AddChild(name); |
| 404 canonical_names_[canonical_names_entries_read_] = canonical_name; |
| 405 } |
| 406 |
| 407 canonical_names_next_offset_ = ReaderOffset(); |
| 408 |
| 409 SetOffset(saved_offset); |
| 410 return canonical_names_[index]; |
| 411 } |
| 412 |
| 298 intptr_t StreamingFlowGraphBuilder::ReaderOffset() { | 413 intptr_t StreamingFlowGraphBuilder::ReaderOffset() { |
| 299 return reader_->offset(); | 414 return reader_->offset(); |
| 300 } | 415 } |
| 301 | 416 |
| 302 void StreamingFlowGraphBuilder::SetOffset(intptr_t offset) { | 417 void StreamingFlowGraphBuilder::SetOffset(intptr_t offset) { |
| 303 reader_->set_offset(offset); | 418 reader_->set_offset(offset); |
| 304 } | 419 } |
| 305 | 420 |
| 306 void StreamingFlowGraphBuilder::SkipBytes(intptr_t bytes) { | 421 void StreamingFlowGraphBuilder::SkipBytes(intptr_t bytes) { |
| 307 reader_->set_offset(ReaderOffset() + bytes); | 422 reader_->set_offset(ReaderOffset() + bytes); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 intptr_t saved_offset = ReaderOffset(); | 465 intptr_t saved_offset = ReaderOffset(); |
| 351 | 466 |
| 352 SetOffset(GetStringTableOffset(str_index)); | 467 SetOffset(GetStringTableOffset(str_index)); |
| 353 uint32_t bytes = ReadUInt(); | 468 uint32_t bytes = ReadUInt(); |
| 354 const uint8_t* data = &reader_->buffer()[ReaderOffset()]; | 469 const uint8_t* data = &reader_->buffer()[ReaderOffset()]; |
| 355 | 470 |
| 356 SetOffset(saved_offset); | 471 SetOffset(saved_offset); |
| 357 return H.DartString(data, bytes); | 472 return H.DartString(data, bytes); |
| 358 } | 473 } |
| 359 | 474 |
| 475 String* StreamingFlowGraphBuilder::KernelString(intptr_t str_index) { |
| 476 intptr_t savedOffset = ReaderOffset(); |
| 477 |
| 478 SetOffset(GetStringTableOffset(str_index)); |
| 479 uint32_t bytes = ReadUInt(); |
| 480 const uint8_t* data = &reader_->buffer()[ReaderOffset()]; |
| 481 |
| 482 SetOffset(savedOffset); |
| 483 return new String(data, bytes); |
| 484 } |
| 485 |
| 360 Fragment StreamingFlowGraphBuilder::DebugStepCheck(TokenPosition position) { | 486 Fragment StreamingFlowGraphBuilder::DebugStepCheck(TokenPosition position) { |
| 361 return flow_graph_builder_->DebugStepCheck(position); | 487 return flow_graph_builder_->DebugStepCheck(position); |
| 362 } | 488 } |
| 363 | 489 |
| 364 Fragment StreamingFlowGraphBuilder::LoadLocal(LocalVariable* variable) { | 490 Fragment StreamingFlowGraphBuilder::LoadLocal(LocalVariable* variable) { |
| 365 return flow_graph_builder_->LoadLocal(variable); | 491 return flow_graph_builder_->LoadLocal(variable); |
| 366 } | 492 } |
| 367 | 493 |
| 368 Fragment StreamingFlowGraphBuilder::PushArgument() { | 494 Fragment StreamingFlowGraphBuilder::PushArgument() { |
| 369 return flow_graph_builder_->PushArgument(); | 495 return flow_graph_builder_->PushArgument(); |
| 370 } | 496 } |
| 371 | 497 |
| 372 Fragment StreamingFlowGraphBuilder::RethrowException(TokenPosition position, | 498 Fragment StreamingFlowGraphBuilder::RethrowException(TokenPosition position, |
| 373 int catch_try_index) { | 499 int catch_try_index) { |
| 374 return flow_graph_builder_->RethrowException(position, catch_try_index); | 500 return flow_graph_builder_->RethrowException(position, catch_try_index); |
| 375 } | 501 } |
| 376 | 502 |
| 377 Fragment StreamingFlowGraphBuilder::ThrowNoSuchMethodError() { | 503 Fragment StreamingFlowGraphBuilder::ThrowNoSuchMethodError() { |
| 378 return flow_graph_builder_->ThrowNoSuchMethodError(); | 504 return flow_graph_builder_->ThrowNoSuchMethodError(); |
| 379 } | 505 } |
| 380 | 506 |
| 381 Fragment StreamingFlowGraphBuilder::Constant(const Object& value) { | 507 Fragment StreamingFlowGraphBuilder::Constant(const Object& value) { |
| 382 return flow_graph_builder_->Constant(value); | 508 return flow_graph_builder_->Constant(value); |
| 383 } | 509 } |
| 384 | 510 |
| 385 Fragment StreamingFlowGraphBuilder::IntConstant(int64_t value) { | 511 Fragment StreamingFlowGraphBuilder::IntConstant(int64_t value) { |
| 386 return flow_graph_builder_->IntConstant(value); | 512 return flow_graph_builder_->IntConstant(value); |
| 387 } | 513 } |
| 388 | 514 |
| 515 Fragment StreamingFlowGraphBuilder::LoadStaticField() { |
| 516 return flow_graph_builder_->LoadStaticField(); |
| 517 } |
| 518 |
| 519 Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position, |
| 520 const Function& target, |
| 521 intptr_t argument_count) { |
| 522 return flow_graph_builder_->StaticCall(position, target, argument_count); |
| 523 } |
| 524 |
| 389 Fragment StreamingFlowGraphBuilder::BuildInvalidExpression() { | 525 Fragment StreamingFlowGraphBuilder::BuildInvalidExpression() { |
| 390 // The frontend will take care of emitting normal errors (like | 526 // The frontend will take care of emitting normal errors (like |
| 391 // [NoSuchMethodError]s) and only emit [InvalidExpression]s in very special | 527 // [NoSuchMethodError]s) and only emit [InvalidExpression]s in very special |
| 392 // situations (e.g. an invalid annotation). | 528 // situations (e.g. an invalid annotation). |
| 393 return ThrowNoSuchMethodError(); | 529 return ThrowNoSuchMethodError(); |
| 394 } | 530 } |
| 395 | 531 |
| 532 Fragment StreamingFlowGraphBuilder::BuildStaticGet() { |
| 533 intptr_t saved_offset = ReaderOffset() - 1; // Include the tag. |
| 534 TokenPosition position = ReadPosition(); |
| 535 int canonical_name_index = ReadUInt(); |
| 536 CanonicalName* target = GetCanonicalName(canonical_name_index); |
| 537 |
| 538 if (target->IsField()) { |
| 539 const dart::Field& field = |
| 540 dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(target)); |
| 541 if (field.is_const()) { |
| 542 SetOffset(saved_offset); // EvaluateExpression needs the tag. |
| 543 return Constant(constant_evaluator_.EvaluateExpression()); |
| 544 } else { |
| 545 const dart::Class& owner = dart::Class::Handle(Z, field.Owner()); |
| 546 const dart::String& getter_name = H.DartGetterName(target); |
| 547 const Function& getter = |
| 548 Function::ZoneHandle(Z, owner.LookupStaticFunction(getter_name)); |
| 549 if (getter.IsNull() || !field.has_initializer()) { |
| 550 Fragment instructions = Constant(field); |
| 551 return instructions + LoadStaticField(); |
| 552 } else { |
| 553 return StaticCall(position, getter, 0); |
| 554 } |
| 555 } |
| 556 } else { |
| 557 const Function& function = |
| 558 Function::ZoneHandle(Z, H.LookupStaticMethodByKernelProcedure(target)); |
| 559 |
| 560 if (target->IsGetter()) { |
| 561 return StaticCall(position, function, 0); |
| 562 } else if (target->IsMethod()) { |
| 563 SetOffset(saved_offset); // EvaluateExpression needs the tag. |
| 564 return Constant(constant_evaluator_.EvaluateExpression()); |
| 565 } else { |
| 566 UNIMPLEMENTED(); |
| 567 } |
| 568 } |
| 569 |
| 570 return Fragment(); |
| 571 } |
| 572 |
| 396 Fragment StreamingFlowGraphBuilder::BuildSymbolLiteral() { | 573 Fragment StreamingFlowGraphBuilder::BuildSymbolLiteral() { |
| 397 SkipBytes(-1); // EvaluateExpression needs the tag. | 574 SkipBytes(-1); // EvaluateExpression needs the tag. |
| 398 return Constant(constant_evaluator_.EvaluateExpression()); | 575 return Constant(constant_evaluator_.EvaluateExpression()); |
| 399 } | 576 } |
| 400 | 577 |
| 401 Fragment StreamingFlowGraphBuilder::BuildThisExpression() { | 578 Fragment StreamingFlowGraphBuilder::BuildThisExpression() { |
| 402 return LoadLocal(scopes()->this_variable); | 579 return LoadLocal(scopes()->this_variable); |
| 403 } | 580 } |
| 404 | 581 |
| 405 Fragment StreamingFlowGraphBuilder::BuildRethrow() { | 582 Fragment StreamingFlowGraphBuilder::BuildRethrow() { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 444 } | 621 } |
| 445 | 622 |
| 446 Fragment StreamingFlowGraphBuilder::BuildNullLiteral() { | 623 Fragment StreamingFlowGraphBuilder::BuildNullLiteral() { |
| 447 return Constant(Instance::ZoneHandle(Z, Instance::null())); | 624 return Constant(Instance::ZoneHandle(Z, Instance::null())); |
| 448 } | 625 } |
| 449 | 626 |
| 450 } // namespace kernel | 627 } // namespace kernel |
| 451 } // namespace dart | 628 } // namespace dart |
| 452 | 629 |
| 453 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 630 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
| OLD | NEW |