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

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 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 310
309 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) { 311 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) {
310 ReturnComputation(new ConstantVal(node->literal())); 312 ReturnComputation(new ConstantVal(node->literal()));
311 } 313 }
312 314
313 // Type nodes only occur as the right-hand side of instanceof comparisons, 315 // Type nodes only occur as the right-hand side of instanceof comparisons,
314 // and they are handled specially in that context. 316 // and they are handled specially in that context.
315 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); } 317 void EffectGraphVisitor::VisitTypeNode(TypeNode* node) { UNREACHABLE(); }
316 318
317 319
318 // Returns true if the type check can be skipped, for example, if the 320 // Helper routine returning true if the static type of the given value is more
319 // destination type is Dynamic or if the static type of the value is a subtype 321 // specific than the given dst_type.
320 // of the destination type. 322 static bool IsStaticTypeMoreSpecific(Value* value,
321 static bool CanSkipTypeCheck(Value* value, const AbstractType& dst_type) { 323 const AbstractType& dst_type) {
322 ASSERT(!dst_type.IsNull()); 324 ASSERT(!dst_type.IsMalformed());
323 ASSERT(dst_type.IsFinalized());
324 if (!FLAG_eliminate_type_checks) {
325 return false;
326 }
327 325
328 // Any expression is assignable to the Dynamic type and to the Object type. 326 // Any type is more specific than the Dynamic type and than the Object type.
329 // Skip the test. 327 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) {
330 if (!dst_type.IsMalformed() &&
331 (dst_type.IsDynamicType() || dst_type.IsObjectType())) {
332 return true; 328 return true;
333 } 329 }
334 330
335 // It is a compile-time error to explicitly return a value (including null) 331 // It is a compile-time error to explicitly return a value (including null)
336 // from a void function. However, functions that do not explicitly return a 332 // from a void function. However, functions that do not explicitly return a
337 // value, implicitly return null. This includes void functions. Therefore, we 333 // value, implicitly return null. This includes void functions. Therefore, we
338 // skip the type test here and trust the parser to only return null in void 334 // skip the type test here and trust the parser to only return null in void
339 // function. 335 // function.
340 if (dst_type.IsVoidType()) { 336 if (dst_type.IsVoidType()) {
337 // TODO(regis): Should we perform this null test at run-time?
341 return true; 338 return true;
342 } 339 }
343 340
341 // Do not perform type check elimination if this optimization is turned off.
342 if (!FLAG_eliminate_type_checks) {
343 return false;
344 }
345
344 // If nothing is known about the value, as is the case for passed-in 346 // If nothing is known about the value, as is the case for passed-in
345 // parameters, the test cannot be eliminated. 347 // parameters, the type test cannot be eliminated.
srdjan 2012/07/07 23:06:04 The comment is confusing as it implies how the met
regis 2012/07/09 16:58:53 Moving this test to the caller would skip the test
346 if (value == NULL) { 348 if (value == NULL) {
347 return false; 349 return false;
348 } 350 }
349 351
350 // Consider the static type of the value. 352 // Consider the static type of the value.
351 const AbstractType& static_type = AbstractType::Handle(value->StaticType()); 353 const AbstractType& static_type = AbstractType::Handle(value->StaticType());
352 ASSERT(!static_type.IsMalformed()); 354 ASSERT(!static_type.IsMalformed());
353 355
354 // If the static type of the value is void, the only allowed value is null, 356 // If the static type of the value is void, the only allowed value is null,
355 // which must be verified by the type test. 357 // which must be verified by the type test.
358 // TODO(regis): Eliminate the test if the value is constant null.
srdjan 2012/07/07 23:06:04 ditto
regis 2012/07/09 16:58:53 ditto
356 if (static_type.IsVoidType()) { 359 if (static_type.IsVoidType()) {
357 // TODO(regis): Eliminate the test if the value is constant null.
358 return false; 360 return false;
359 } 361 }
360 362
361 // If the static type of the value is NullType, the type test is eliminated. 363 // If the static type of the value is NullType, the type test is eliminated.
364 // There are only three instances that can be of Class Null:
365 // Object::null(), Object::sentinel(), and Object::transition_sentinel().
366 // The inline code and run time code performing the type check will never
367 // encounter the 2 sentinel values. The type check of a sentinel value
368 // will always be eliminated here, because these sentinel values can only
369 // be encountered as constants, never as actual value of a heap object
370 // being type checked.
362 if (static_type.IsNullType()) { 371 if (static_type.IsNullType()) {
363 // There are only three instances that can be of Class Null:
364 // Object::null(), Object::sentinel(), and Object::transition_sentinel().
365 // The inline code and run time code performing the type check will never
366 // encounter the 2 sentinel values. The type check of a sentinel value
367 // will always be eliminated here, because these sentinel values can only
368 // be encountered as constants, never as actual value of a heap object
369 // being type checked.
370 return true; 372 return true;
371 } 373 }
372 374
373 // The run time type of the value is guaranteed to be a subtype of the compile 375 // The run time type of the value is guaranteed to be a subtype of the
374 // time static type of the value. However, establishing here that the static 376 // compile time static type of the value. However, establishing here that
375 // type is a subtype of the destination type does not guarantee that the run 377 // the static type is a subtype of the destination type does not guarantee
376 // time type will also be a subtype of the destination type, because the 378 // that the run time type will also be a subtype of the destination type,
377 // subtype relation is not transitive. 379 // because the subtype relation is not transitive.
378 // However, the 'more specific than' relation is transitive and is used here. 380 // However, the 'more specific than' relation is transitive and is used
379 // In other words, if the static type of the value is more specific than the 381 // here. In other words, if the static type of the value is more specific
380 // destination type, the run time type of the value, which is guaranteed to 382 // than the destination type, the run time type of the value, which is
381 // be a subtype of the static type, is also guaranteed to be a subtype of the 383 // guaranteed to be a subtype of the static type, is also guaranteed to be
382 // destination type and the type check can therefore be eliminated. 384 // a subtype of the destination type and the type check can therefore be
385 // eliminated.
383 Error& malformed_error = Error::Handle(); 386 Error& malformed_error = Error::Handle();
384 if (static_type.IsMoreSpecificThan(dst_type, &malformed_error)) { 387 return static_type.IsMoreSpecificThan(dst_type, &malformed_error);
385 return true;
386 }
387
388 return false;
389 } 388 }
390 389
391 390
391 // Returns true if the type check can be skipped, for example, if the
392 // destination type is Dynamic or if the static type of the value is a subtype
393 // of the destination type.
394 bool EffectGraphVisitor::CanSkipTypeCheck(intptr_t token_pos,
395 Value* value,
396 const AbstractType& dst_type,
397 const String& dst_name) {
398 ASSERT(!dst_type.IsNull());
399 ASSERT(dst_type.IsFinalized());
400
401 // If the destination type is malformed, a dynamic type error must be thrown
402 // at run time.
403 if (dst_type.IsMalformed()) {
404 return false;
405 }
406
407 const bool eliminated = IsStaticTypeMoreSpecific(value, dst_type);
408 if (FLAG_eliminate_type_checks && FLAG_trace_type_check_elimination) {
409 const Class& cls = Class::Handle(
410 owner()->parsed_function().function().owner());
411 const Script& script = Script::Handle(cls.script());
412 const char* static_type_name = "unknown";
413 if (value != NULL) {
414 const AbstractType& type = AbstractType::Handle(value->StaticType());
415 static_type_name = String::Handle(type.Name()).ToCString();
416 }
417 Parser::PrintMessage(script, token_pos, "",
418 "%s type check: static type '%s' is %s specific than "
419 "type '%s' of '%s'.",
420 eliminated ? "Eliminated" : "Generated",
421 static_type_name,
422 eliminated ? "more" : "not more",
423 String::Handle(dst_type.Name()).ToCString(),
424 dst_name.ToCString());
425 }
426 return eliminated;
427 }
428
429
392 // <Expression> :: Assignable { expr: <Expression> 430 // <Expression> :: Assignable { expr: <Expression>
393 // type: AbstractType 431 // type: AbstractType
394 // dst_name: String } 432 // dst_name: String }
395 void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) { 433 void EffectGraphVisitor::VisitAssignableNode(AssignableNode* node) {
396 UNREACHABLE(); 434 UNREACHABLE();
397 } 435 }
398 436
399 437
400 void ValueGraphVisitor::VisitAssignableNode(AssignableNode* node) { 438 void ValueGraphVisitor::VisitAssignableNode(AssignableNode* node) {
401 ValueGraphVisitor for_value(owner(), temp_index()); 439 ValueGraphVisitor for_value(owner(), temp_index());
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 dst_type, 700 dst_type,
663 dst_name); 701 dst_name);
664 } 702 }
665 703
666 704
667 // Used for type casts and to test assignments. 705 // Used for type casts and to test assignments.
668 Value* EffectGraphVisitor::BuildAssignableValue(intptr_t token_pos, 706 Value* EffectGraphVisitor::BuildAssignableValue(intptr_t token_pos,
669 Value* value, 707 Value* value,
670 const AbstractType& dst_type, 708 const AbstractType& dst_type,
671 const String& dst_name) { 709 const String& dst_name) {
672 if (CanSkipTypeCheck(value, dst_type)) { 710 if (CanSkipTypeCheck(token_pos, value, dst_type, dst_name)) {
673 return value; 711 return value;
674 } 712 }
675 AssertAssignableComp* comp = BuildAssertAssignable(token_pos, 713 AssertAssignableComp* comp = BuildAssertAssignable(token_pos,
676 value, 714 value,
677 dst_type, 715 dst_type,
678 dst_name); 716 dst_name);
679 BindInstr* assert_assignable = new BindInstr(comp); 717 BindInstr* assert_assignable = new BindInstr(comp);
680 AddInstruction(assert_assignable); 718 AddInstruction(assert_assignable);
681 return new UseVal(assert_assignable); 719 return new UseVal(assert_assignable);
682 } 720 }
683 721
684 722
685 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) { 723 void EffectGraphVisitor::BuildTypeTest(ComparisonNode* node) {
686 ASSERT(Token::IsTypeTestOperator(node->kind())); 724 ASSERT(Token::IsTypeTestOperator(node->kind()));
687 EffectGraphVisitor for_left_value(owner(), temp_index()); 725 EffectGraphVisitor for_left_value(owner(), temp_index());
688 node->left()->Visit(&for_left_value); 726 node->left()->Visit(&for_left_value);
689 Append(for_left_value); 727 Append(for_left_value);
690 } 728 }
691 729
692 730
693 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) { 731 void EffectGraphVisitor::BuildTypeCast(ComparisonNode* node) {
694 ASSERT(Token::IsTypeCastOperator(node->kind())); 732 ASSERT(Token::IsTypeCastOperator(node->kind()));
695 const AbstractType& type = node->right()->AsTypeNode()->type(); 733 const AbstractType& type = node->right()->AsTypeNode()->type();
696 ASSERT(type.IsFinalized()); // The type in a type cast may be malformed. 734 ASSERT(type.IsFinalized()); // The type in a type cast may be malformed.
697 ValueGraphVisitor for_value(owner(), temp_index()); 735 ValueGraphVisitor for_value(owner(), temp_index());
698 node->left()->Visit(&for_value); 736 node->left()->Visit(&for_value);
699 Append(for_value); 737 Append(for_value);
700 const String& dst_name = String::ZoneHandle( 738 const String& dst_name = String::ZoneHandle(
701 String::NewSymbol(Exceptions::kCastExceptionDstName)); 739 String::NewSymbol(Exceptions::kCastExceptionDstName));
702 if (!CanSkipTypeCheck(for_value.value(), type)) { 740 if (!CanSkipTypeCheck(node->token_pos(), for_value.value(), type, dst_name)) {
703 AssertAssignableComp* assert_assignable = 741 AssertAssignableComp* assert_assignable =
704 BuildAssertAssignable(node->token_pos(), 742 BuildAssertAssignable(node->token_pos(),
705 for_value.value(), 743 for_value.value(),
706 type, 744 type,
707 dst_name); 745 dst_name);
708 AddInstruction(new DoInstr(assert_assignable)); 746 AddInstruction(new DoInstr(assert_assignable));
709 } 747 }
710 } 748 }
711 749
712 750
(...skipping 1470 matching lines...) Expand 10 before | Expand all | Expand 10 after
2183 // Skip type checking of receiver and phase for constructor functions. 2221 // Skip type checking of receiver and phase for constructor functions.
2184 pos = 2; 2222 pos = 2;
2185 } else if (function.IsFactory() || function.IsDynamicFunction()) { 2223 } else if (function.IsFactory() || function.IsDynamicFunction()) {
2186 // Skip type checking of type arguments for factory functions. 2224 // Skip type checking of type arguments for factory functions.
2187 // Skip type checking of receiver for instance functions. 2225 // Skip type checking of receiver for instance functions.
2188 pos = 1; 2226 pos = 1;
2189 } 2227 }
2190 while (pos < num_params) { 2228 while (pos < num_params) {
2191 const LocalVariable& parameter = *scope->VariableAt(pos); 2229 const LocalVariable& parameter = *scope->VariableAt(pos);
2192 ASSERT(parameter.owner() == scope); 2230 ASSERT(parameter.owner() == scope);
2193 if (!CanSkipTypeCheck(NULL, parameter.type())) { 2231 if (!CanSkipTypeCheck(parameter.token_pos(),
2232 NULL,
2233 parameter.type(),
2234 parameter.name())) {
2194 BindInstr* load = new BindInstr(BuildLoadLocal(parameter)); 2235 BindInstr* load = new BindInstr(BuildLoadLocal(parameter));
2195 AddInstruction(load); 2236 AddInstruction(load);
2196 AssertAssignableComp* assert_assignable = 2237 AssertAssignableComp* assert_assignable =
2197 BuildAssertAssignable(parameter.token_pos(), 2238 BuildAssertAssignable(parameter.token_pos(),
2198 new UseVal(load), 2239 new UseVal(load),
2199 parameter.type(), 2240 parameter.type(),
2200 parameter.name()); 2241 parameter.name());
2201 AddInstruction(new DoInstr(assert_assignable)); 2242 AddInstruction(new DoInstr(assert_assignable));
2202 } 2243 }
2203 pos++; 2244 pos++;
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after
2799 char* chars = reinterpret_cast<char*>( 2840 char* chars = reinterpret_cast<char*>(
2800 Isolate::Current()->current_zone()->Allocate(len)); 2841 Isolate::Current()->current_zone()->Allocate(len));
2801 OS::SNPrint(chars, len, kFormat, function_name, reason); 2842 OS::SNPrint(chars, len, kFormat, function_name, reason);
2802 const Error& error = Error::Handle( 2843 const Error& error = Error::Handle(
2803 LanguageError::New(String::Handle(String::New(chars)))); 2844 LanguageError::New(String::Handle(String::New(chars))));
2804 Isolate::Current()->long_jump_base()->Jump(1, error); 2845 Isolate::Current()->long_jump_base()->Jump(1, error);
2805 } 2846 }
2806 2847
2807 2848
2808 } // namespace dart 2849 } // 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