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 |