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

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

Issue 10830109: Add type propagation phase in optimizing compiler (work in progress). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/flow_graph_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "vm/ast_printer.h" 7 #include "vm/ast_printer.h"
8 #include "vm/bit_vector.h" 8 #include "vm/bit_vector.h"
9 #include "vm/code_descriptors.h" 9 #include "vm/code_descriptors.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) { 392 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) {
393 ReturnComputation(new ConstantVal(node->literal())); 393 ReturnComputation(new ConstantVal(node->literal()));
394 } 394 }
395 395
396 396
397 // Type nodes only occur as the right-hand side of instanceof comparisons, 397 // Type nodes only occur as the right-hand side of instanceof comparisons,
398 // and they are handled specially in that context. 398 // and they are handled specially in that context.
399 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } 399 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); }
400 400
401 401
402 // Helper routine returning true if the static type of the given value is more 402 // Returns true if the type check can be skipped, for example, if the
403 // specific than the given dst_type. 403 // destination type is Dynamic or if the static type of the value is a subtype
404 static bool IsStaticTypeMoreSpecific(Value* value, 404 // of the destination type.
405 const AbstractType& dst_type) { 405 bool EffectGraphVisitor::CanSkipTypeCheck(intptr_t token_pos,
406 ASSERT(!dst_type.IsMalformed()); 406 Value* value,
407 const AbstractType& dst_type,
408 const String& dst_name) {
409 ASSERT(!dst_type.IsNull());
410 ASSERT(dst_type.IsFinalized());
411
412 // If the destination type is malformed, a dynamic type error must be thrown
413 // at run time.
414 if (dst_type.IsMalformed()) {
415 return false;
416 }
407 417
408 // Any type is more specific than the Dynamic type and than the Object type. 418 // Any type is more specific than the Dynamic type and than the Object type.
409 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { 419 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) {
410 return true; 420 return true;
411 } 421 }
412 422
413 // Do not perform type check elimination if this optimization is turned off. 423 // Do not perform type check elimination if this optimization is turned off.
414 if (!FLAG_eliminate_type_checks) { 424 if (!FLAG_eliminate_type_checks) {
415 return false; 425 return false;
416 } 426 }
417 427
418 // If nothing is known about the value, as is the case for passed-in 428 // If nothing is known about the value, as is the case for passed-in
419 // parameters, and since dst_type is not one of the tested cases above, then 429 // parameters, and since dst_type is not one of the tested cases above, then
420 // the type test cannot be eliminated. 430 // the type test cannot be eliminated.
421 if (value == NULL) { 431 if (value == NULL) {
422 return false; 432 return false;
423 } 433 }
424 434
425 // If the value is the null constant, its type (NullType) is more specific 435 const bool eliminated = value->StaticTypeIsMoreSpecificThan(dst_type);
426 // than the destination type, even if the destination type is the void type, 436 if (FLAG_trace_type_check_elimination) {
427 // since a void function is allowed to return null. 437 FlowGraphPrinter::PrintTypeCheck(owner()->parsed_function(),
428 if (value->IsConstant() && value->AsConstant()->value().IsNull()) { 438 token_pos,
429 return true; 439 value,
430 } 440 dst_type,
431 441 dst_name,
432 // Functions that do not explicitly return a value, implicitly return null, 442 eliminated);
433 // except generative constructors, which return the object being constructed.
434 // It is therefore acceptable for void functions to return null.
435 // In case of a null constant, we have already returned true above, else we
436 // return false here.
437 if (dst_type.IsVoidType()) {
438 return false;
439 }
440
441 // Consider the static type of the value.
442 const AbstractType& static_type = AbstractType::Handle(value->StaticType());
443 ASSERT(!static_type.IsMalformed());
444
445 // If the static type of the value is void, we are type checking the result of
446 // a void function, which was checked to be null at the return statement
447 // inside the function.
448 if (static_type.IsVoidType()) {
449 return true;
450 }
451
452 // If the static type of the value is NullType, the type test is eliminated.
453 // There are only three instances that can be of Class Null:
454 // Object::null(), Object::sentinel(), and Object::transition_sentinel().
455 // The inline code and run time code performing the type check will never
456 // encounter the 2 sentinel values. The type check of a sentinel value
457 // will always be eliminated here, because these sentinel values can only
458 // be encountered as constants, never as actual value of a heap object
459 // being type checked.
460 if (static_type.IsNullType()) {
461 return true;
462 }
463
464 // The run time type of the value is guaranteed to be a subtype of the
465 // compile time static type of the value. However, establishing here that
466 // the static type is a subtype of the destination type does not guarantee
467 // that the run time type will also be a subtype of the destination type,
468 // because the subtype relation is not transitive.
469 // However, the 'more specific than' relation is transitive and is used
470 // here. In other words, if the static type of the value is more specific
471 // than the destination type, the run time type of the value, which is
472 // guaranteed to be a subtype of the static type, is also guaranteed to be
473 // a subtype of the destination type and the type check can therefore be
474 // eliminated.
475 return static_type.IsMoreSpecificThan(dst_type, NULL);
476 }
477
478
479 // Returns true if the type check can be skipped, for example, if the
480 // destination type is Dynamic or if the static type of the value is a subtype
481 // of the destination type.
482 bool EffectGraphVisitor::CanSkipTypeCheck(intptr_t token_pos,
483 Value* value,
484 const AbstractType& dst_type,
485 const String& dst_name) {
486 ASSERT(!dst_type.IsNull());
487 ASSERT(dst_type.IsFinalized());
488
489 // If the destination type is malformed, a dynamic type error must be thrown
490 // at run time.
491 if (dst_type.IsMalformed()) {
492 return false;
493 }
494
495 const bool eliminated = IsStaticTypeMoreSpecific(value, dst_type);
496 if (FLAG_eliminate_type_checks && FLAG_trace_type_check_elimination) {
497 const Class& cls = Class::Handle(
498 owner()->parsed_function().function().owner());
499 const Script& script = Script::Handle(cls.script());
500 const char* static_type_name = "unknown";
501 if (value != NULL) {
502 const AbstractType& type = AbstractType::Handle(value->StaticType());
503 static_type_name = String::Handle(type.UserVisibleName()).ToCString();
504 }
505 Parser::PrintMessage(script, token_pos, "",
506 "%s type check: static type '%s' is %s specific than "
507 "type '%s' of '%s'.",
508 eliminated ? "Eliminated" : "Generated",
509 static_type_name,
510 eliminated ? "more" : "not more",
511 String::Handle(dst_type.UserVisibleName()).ToCString(),
512 dst_name.ToCString());
513 } 443 }
514 return eliminated; 444 return eliminated;
515 } 445 }
516 446
517 447
518 // <Expression> :: Assignable { expr: <Expression> 448 // <Expression> :: Assignable { expr: <Expression>
519 // type: AbstractType 449 // type: AbstractType
520 // dst_name: String } 450 // dst_name: String }
521 void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) { 451 void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) {
522 UNREACHABLE(); 452 UNREACHABLE();
(...skipping 2227 matching lines...) Expand 10 before | Expand all | Expand 10 after
2750 char* chars = reinterpret_cast<char*>( 2680 char* chars = reinterpret_cast<char*>(
2751 Isolate::Current()->current_zone()->Allocate(len)); 2681 Isolate::Current()->current_zone()->Allocate(len));
2752 OS::SNPrint(chars, len, kFormat, function_name, reason); 2682 OS::SNPrint(chars, len, kFormat, function_name, reason);
2753 const Error& error = Error::Handle( 2683 const Error& error = Error::Handle(
2754 LanguageError::New(String::Handle(String::New(chars)))); 2684 LanguageError::New(String::Handle(String::New(chars))));
2755 Isolate::Current()->long_jump_base()->Jump(1, error); 2685 Isolate::Current()->long_jump_base()->Jump(1, error);
2756 } 2686 }
2757 2687
2758 2688
2759 } // namespace dart 2689 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698