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

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

Issue 10689099: Add --trace_type_check_elimination flag for debugging purposes. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 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
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/parser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
11 #include "vm/flags.h" 11 #include "vm/flags.h"
12 #include "vm/il_printer.h" 12 #include "vm/il_printer.h"
13 #include "vm/intermediate_language.h" 13 #include "vm/intermediate_language.h"
14 #include "vm/longjump.h" 14 #include "vm/longjump.h"
15 #include "vm/object_store.h" 15 #include "vm/object_store.h"
16 #include "vm/os.h" 16 #include "vm/os.h"
17 #include "vm/parser.h" 17 #include "vm/parser.h"
18 #include "vm/resolver.h" 18 #include "vm/resolver.h"
19 #include "vm/stub_code.h" 19 #include "vm/stub_code.h"
20 20
21 namespace dart { 21 namespace dart {
22 22
23 DEFINE_FLAG(bool, eliminate_type_checks, true, 23 DEFINE_FLAG(bool, eliminate_type_checks, true,
24 "Eliminate type checks when allowed by static type analysis"); 24 "Eliminate type checks when allowed by static type analysis.");
25 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree."); 25 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree.");
26 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph."); 26 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph.");
27 DEFINE_FLAG(bool, trace_type_check_elimination, false,
28 "Trace type check elimination at compile time.");
27 #if defined(TARGET_ARCH_X64) 29 #if defined(TARGET_ARCH_X64)
28 DEFINE_FLAG(bool, use_ssa, true, "Use SSA form"); 30 DEFINE_FLAG(bool, use_ssa, true, "Use SSA form");
29 #else 31 #else
30 DEFINE_FLAG(bool, use_ssa, false, "Use SSA form"); 32 DEFINE_FLAG(bool, use_ssa, false, "Use SSA form");
31 #endif 33 #endif
32 DECLARE_FLAG(bool, enable_type_checks); 34 DECLARE_FLAG(bool, enable_type_checks);
33 35
34 36
35 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function) 37 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function)
36 : parsed_function_(parsed_function), 38 : parsed_function_(parsed_function),
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 322
321 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) { 323 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) {
322 ReturnComputation(new ConstantVal(node->literal())); 324 ReturnComputation(new ConstantVal(node->literal()));
323 } 325 }
324 326
325 // Type nodes only occur as the right-hand side of instanceof comparisons, 327 // Type nodes only occur as the right-hand side of instanceof comparisons,
326 // and they are handled specially in that context. 328 // and they are handled specially in that context.
327 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } 329 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); }
328 330
329 331
330 // Returns true if the type check can be skipped, for example, if the 332 // Helper routine returning true if the static type of the given value is more
331 // destination type is Dynamic or if the static type of the value is a subtype 333 // specific than the given dst_type.
332 // of the destination type. 334 static bool IsStaticTypeMoreSpecific(Value* value,
333 static bool CanSkipTypeCheck(Value* value, const AbstractType& dst_type) { 335 const AbstractType& dst_type) {
334 ASSERT(!dst_type.IsNull()); 336 ASSERT(!dst_type.IsMalformed());
335 ASSERT(dst_type.IsFinalized());
336 if (!FLAG_eliminate_type_checks) {
337 return false;
338 }
339 337
340 // Any expression is assignable to the Dynamic type and to the Object type. 338 // Any type is more specific than the Dynamic type and than the Object type.
341 // Skip the test. 339 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) {
342 if (!dst_type.IsMalformed() &&
343 (dst_type.IsDynamicType() || dst_type.IsObjectType())) {
344 return true; 340 return true;
345 } 341 }
346 342
347 // It is a compile-time error to explicitly return a value (including null) 343 // It is a compile-time error to explicitly return a value (including null)
348 // from a void function. However, functions that do not explicitly return a 344 // from a void function. However, functions that do not explicitly return a
349 // value, implicitly return null. This includes void functions. Therefore, we 345 // value, implicitly return null. This includes void functions. Therefore, we
350 // skip the type test here and trust the parser to only return null in void 346 // skip the type test here and trust the parser to only return null in void
351 // function. 347 // function.
352 if (dst_type.IsVoidType()) { 348 if (dst_type.IsVoidType()) {
349 // TODO(regis): Should we perform this null test at run-time?
353 return true; 350 return true;
354 } 351 }
355 352
353 // Do not perform type check elimination if this optimization is turned off.
354 if (!FLAG_eliminate_type_checks) {
355 return false;
356 }
357
356 // If nothing is known about the value, as is the case for passed-in 358 // If nothing is known about the value, as is the case for passed-in
357 // parameters, the test cannot be eliminated. 359 // parameters, and since dst_type is not one of the tested cases above, then
360 // the type test cannot be eliminated.
358 if (value == NULL) { 361 if (value == NULL) {
359 return false; 362 return false;
360 } 363 }
361 364
362 // Consider the static type of the value. 365 // Consider the static type of the value.
363 const AbstractType& static_type = AbstractType::Handle(value->StaticType()); 366 const AbstractType& static_type = AbstractType::Handle(value->StaticType());
364 ASSERT(!static_type.IsMalformed()); 367 ASSERT(!static_type.IsMalformed());
365 368
366 // If the static type of the value is void, the only allowed value is null, 369 // If the static type of the value is void, the only allowed value is null,
367 // which must be verified by the type test. 370 // which must be verified by the type test.
371 // TODO(regis): Eliminate the test if the value is constant null.
368 if (static_type.IsVoidType()) { 372 if (static_type.IsVoidType()) {
369 // TODO(regis): Eliminate the test if the value is constant null.
370 return false; 373 return false;
371 } 374 }
372 375
373 // If the static type of the value is NullType, the type test is eliminated. 376 // If the static type of the value is NullType, the type test is eliminated.
377 // There are only three instances that can be of Class Null:
378 // Object::null(), Object::sentinel(), and Object::transition_sentinel().
379 // The inline code and run time code performing the type check will never
380 // encounter the 2 sentinel values. The type check of a sentinel value
381 // will always be eliminated here, because these sentinel values can only
382 // be encountered as constants, never as actual value of a heap object
383 // being type checked.
374 if (static_type.IsNullType()) { 384 if (static_type.IsNullType()) {
375 // There are only three instances that can be of Class Null:
376 // Object::null(), Object::sentinel(), and Object::transition_sentinel().
377 // The inline code and run time code performing the type check will never
378 // encounter the 2 sentinel values. The type check of a sentinel value
379 // will always be eliminated here, because these sentinel values can only
380 // be encountered as constants, never as actual value of a heap object
381 // being type checked.
382 return true; 385 return true;
383 } 386 }
384 387
385 // The run time type of the value is guaranteed to be a subtype of the compile 388 // The run time type of the value is guaranteed to be a subtype of the
386 // time static type of the value. However, establishing here that the static 389 // compile time static type of the value. However, establishing here that
387 // type is a subtype of the destination type does not guarantee that the run 390 // the static type is a subtype of the destination type does not guarantee
388 // time type will also be a subtype of the destination type, because the 391 // that the run time type will also be a subtype of the destination type,
389 // subtype relation is not transitive. 392 // because the subtype relation is not transitive.
390 // However, the 'more specific than' relation is transitive and is used here. 393 // However, the 'more specific than' relation is transitive and is used
391 // In other words, if the static type of the value is more specific than the 394 // here. In other words, if the static type of the value is more specific
392 // destination type, the run time type of the value, which is guaranteed to 395 // than the destination type, the run time type of the value, which is
393 // be a subtype of the static type, is also guaranteed to be a subtype of the 396 // guaranteed to be a subtype of the static type, is also guaranteed to be
394 // destination type and the type check can therefore be eliminated. 397 // a subtype of the destination type and the type check can therefore be
398 // eliminated.
395 Error& malformed_error = Error::Handle(); 399 Error& malformed_error = Error::Handle();
396 if (static_type.IsMoreSpecificThan(dst_type, &malformed_error)) { 400 return static_type.IsMoreSpecificThan(dst_type, &malformed_error);
397 return true;
398 }
399
400 return false;
401 } 401 }
402 402
403 403
404 // Returns true if the type check can be skipped, for example, if the
405 // destination type is Dynamic or if the static type of the value is a subtype
406 // of the destination type.
407 bool EffectGraphVisitor::CanSkipTypeCheck(intptr_t token_pos,
408 Value* value,
409 const AbstractType& dst_type,
410 const String& dst_name) {
411 ASSERT(!dst_type.IsNull());
412 ASSERT(dst_type.IsFinalized());
413
414 // If the destination type is malformed, a dynamic type error must be thrown
415 // at run time.
416 if (dst_type.IsMalformed()) {
417 return false;
418 }
419
420 const bool eliminated = IsStaticTypeMoreSpecific(value, dst_type);
421 if (FLAG_eliminate_type_checks && FLAG_trace_type_check_elimination) {
422 const Class& cls = Class::Handle(
423 owner()->parsed_function().function().owner());
424 const Script& script = Script::Handle(cls.script());
425 const char* static_type_name = "unknown";
426 if (value != NULL) {
427 const AbstractType& type = AbstractType::Handle(value->StaticType());
428 static_type_name = String::Handle(type.Name()).ToCString();
429 }
430 Parser::PrintMessage(script, token_pos, "",
431 "%s type check: static type '%s' is %s specific than "
432 "type '%s' of '%s'.",
433 eliminated ? "Eliminated" : "Generated",
434 static_type_name,
435 eliminated ? "more" : "not more",
436 String::Handle(dst_type.Name()).ToCString(),
437 dst_name.ToCString());
438 }
439 return eliminated;
440 }
441
442
404 // <Expression> :: Assignable { expr: <Expression> 443 // <Expression> :: Assignable { expr: <Expression>
405 // type: AbstractType 444 // type: AbstractType
406 // dst_name: String } 445 // dst_name: String }
407 void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) { 446 void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) {
408 UNREACHABLE(); 447 UNREACHABLE();
409 } 448 }
410 449
411 450
412 void ValueGraphVisitor::VisitAssignableNode(AssignableNode* node) { 451 void ValueGraphVisitor::VisitAssignableNode(AssignableNode* node) {
413 ValueGraphVisitor for_value(owner(), temp_index()); 452 ValueGraphVisitor for_value(owner(), temp_index());
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 dst_type, 621 dst_type,
583 dst_name); 622 dst_name);
584 } 623 }
585 624
586 625
587 // Used for type casts and to test assignments. 626 // Used for type casts and to test assignments.
588 Value* EffectGraphVisitor::BuildAssignableValue(intptr_t token_pos, 627 Value* EffectGraphVisitor::BuildAssignableValue(intptr_t token_pos,
589 Value* value, 628 Value* value,
590 const AbstractType& dst_type, 629 const AbstractType& dst_type,
591 const String& dst_name) { 630 const String& dst_name) {
592 if (CanSkipTypeCheck(value, dst_type)) { 631 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) {
593 return value; 632 return value;
594 } 633 }
595 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name)); 634 return Bind(BuildAssertAssignable(token_pos, value, dst_type, dst_name));
596 } 635 }
597 636
598 637
599 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) { 638 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
600 ASSERT(Token::IsTypeTestOperator(node->kind())); 639 ASSERT(Token::IsTypeTestOperator(node->kind()));
601 EffectGraphVisitor for_left_value(owner(), temp_index()); 640 EffectGraphVisitor for_left_value(owner(), temp_index());
602 node->left()->Visit(&for_left_value); 641 node->left()->Visit(&for_left_value);
603 Append(for_left_value); 642 Append(for_left_value);
604 } 643 }
605 644
606 645
607 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) { 646 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) {
608 ASSERT(Token::IsTypeCastOperator(node->kind())); 647 ASSERT(Token::IsTypeCastOperator(node->kind()));
609 const AbstractType& type = node->right()->AsTypeNode()->type(); 648 const AbstractType& type = node->right()->AsTypeNode()->type();
610 ASSERT(type.IsFinalized()); // The type in a type cast may be malformed. 649 ASSERT(type.IsFinalized()); // The type in a type cast may be malformed.
611 ValueGraphVisitor for_value(owner(), temp_index()); 650 ValueGraphVisitor for_value(owner(), temp_index());
612 node->left()->Visit(&for_value); 651 node->left()->Visit(&for_value);
613 Append(for_value); 652 Append(for_value);
614 const String& dst_name = String::ZoneHandle( 653 const String& dst_name = String::ZoneHandle(
615 String::NewSymbol(Exceptions::kCastExceptionDstName)); 654 String::NewSymbol(Exceptions::kCastExceptionDstName));
616 if (!CanSkipTypeCheck(for_value.value(), type)) { 655 if (!CanSkipTypeCheck(node->token_pos(), for_value.value(), type, dst_name)) {
617 Do(BuildAssertAssignable( 656 Do(BuildAssertAssignable(
618 node->token_pos(), for_value.value(), type, dst_name)); 657 node->token_pos(), for_value.value(), type, dst_name));
619 } 658 }
620 } 659 }
621 660
622 661
623 void ValueGraphVisitor::BuildTypeTest(ComparisonNode* node) { 662 void ValueGraphVisitor::BuildTypeTest(ComparisonNode* node) {
624 ASSERT(Token::IsTypeTestOperator(node->kind())); 663 ASSERT(Token::IsTypeTestOperator(node->kind()));
625 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 664 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
626 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 665 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
(...skipping 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after
2012 // Skip type checking of receiver and phase for constructor functions. 2051 // Skip type checking of receiver and phase for constructor functions.
2013 pos = 2; 2052 pos = 2;
2014 } else if (function.IsFactory() || function.IsDynamicFunction()) { 2053 } else if (function.IsFactory() || function.IsDynamicFunction()) {
2015 // Skip type checking of type arguments for factory functions. 2054 // Skip type checking of type arguments for factory functions.
2016 // Skip type checking of receiver for instance functions. 2055 // Skip type checking of receiver for instance functions.
2017 pos = 1; 2056 pos = 1;
2018 } 2057 }
2019 while (pos < num_params) { 2058 while (pos < num_params) {
2020 const LocalVariable& parameter = *scope->VariableAt(pos); 2059 const LocalVariable& parameter = *scope->VariableAt(pos);
2021 ASSERT(parameter.owner() == scope); 2060 ASSERT(parameter.owner() == scope);
2022 if (!CanSkipTypeCheck(NULL, parameter.type())) { 2061 if (!CanSkipTypeCheck(parameter.token_pos(),
2062 NULL,
2063 parameter.type(),
2064 parameter.name())) {
2023 Value* load = Bind(BuildLoadLocal(parameter)); 2065 Value* load = Bind(BuildLoadLocal(parameter));
2024 Do(BuildAssertAssignable(parameter.token_pos(), 2066 Do(BuildAssertAssignable(parameter.token_pos(),
2025 load, 2067 load,
2026 parameter.type(), 2068 parameter.type(),
2027 parameter.name())); 2069 parameter.name()));
2028 } 2070 }
2029 pos++; 2071 pos++;
2030 } 2072 }
2031 } 2073 }
2032 2074
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
2619 char* chars = reinterpret_cast<char*>( 2661 char* chars = reinterpret_cast<char*>(
2620 Isolate::Current()->current_zone()->Allocate(len)); 2662 Isolate::Current()->current_zone()->Allocate(len));
2621 OS::SNPrint(chars, len, kFormat, function_name, reason); 2663 OS::SNPrint(chars, len, kFormat, function_name, reason);
2622 const Error& error = Error::Handle( 2664 const Error& error = Error::Handle(
2623 LanguageError::New(String::Handle(String::New(chars)))); 2665 LanguageError::New(String::Handle(String::New(chars))));
2624 Isolate::Current()->long_jump_base()->Jump(1, error); 2666 Isolate::Current()->long_jump_base()->Jump(1, error);
2625 } 2667 }
2626 2668
2627 2669
2628 } // namespace dart 2670 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698