| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/bootstrap.h" | 8 #include "vm/bootstrap.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/constant_propagator.h" | 10 #include "vm/constant_propagator.h" |
| (...skipping 1739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1750 case Token::kBIT_OR: | 1750 case Token::kBIT_OR: |
| 1751 case Token::kBIT_XOR: | 1751 case Token::kBIT_XOR: |
| 1752 replacement = | 1752 replacement = |
| 1753 new BinarySmiOpInstr(op_kind(), | 1753 new BinarySmiOpInstr(op_kind(), |
| 1754 new Value(left()->definition()), | 1754 new Value(left()->definition()), |
| 1755 new Value(right()->definition()), | 1755 new Value(right()->definition()), |
| 1756 Thread::kNoDeoptId); | 1756 Thread::kNoDeoptId); |
| 1757 default: | 1757 default: |
| 1758 break; | 1758 break; |
| 1759 } | 1759 } |
| 1760 if (Token::IsRelationalOperator(op_kind())) { | 1760 } |
| 1761 replacement = new RelationalOpInstr(token_pos(), op_kind(), | 1761 return this; |
| 1762 } |
| 1763 |
| 1764 |
| 1765 ComparisonInstr* CheckedSmiComparisonInstr::CopyWithNewOperands( |
| 1766 Value* left, Value* right) { |
| 1767 UNREACHABLE(); |
| 1768 return NULL; |
| 1769 } |
| 1770 |
| 1771 |
| 1772 Definition* CheckedSmiComparisonInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1773 if ((left()->Type()->ToCid() == kSmiCid) && |
| 1774 (right()->Type()->ToCid() == kSmiCid)) { |
| 1775 Definition* replacement = NULL; |
| 1776 if (Token::IsRelationalOperator(kind())) { |
| 1777 replacement = new RelationalOpInstr(token_pos(), kind(), |
| 1762 new Value(left()->definition()), | 1778 new Value(left()->definition()), |
| 1763 new Value(right()->definition()), | 1779 new Value(right()->definition()), |
| 1764 kSmiCid, | 1780 kSmiCid, |
| 1765 Thread::kNoDeoptId); | 1781 Thread::kNoDeoptId); |
| 1766 } else if (Token::IsEqualityOperator(op_kind())) { | 1782 } else if (Token::IsEqualityOperator(kind())) { |
| 1767 replacement = new EqualityCompareInstr(token_pos(), op_kind(), | 1783 replacement = new EqualityCompareInstr(token_pos(), kind(), |
| 1768 new Value(left()->definition()), | 1784 new Value(left()->definition()), |
| 1769 new Value(right()->definition()), | 1785 new Value(right()->definition()), |
| 1770 kSmiCid, | 1786 kSmiCid, |
| 1771 Thread::kNoDeoptId); | 1787 Thread::kNoDeoptId); |
| 1772 } | 1788 } |
| 1773 if (replacement != NULL) { | 1789 if (replacement != NULL) { |
| 1774 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue); | 1790 flow_graph->InsertBefore(this, replacement, env(), FlowGraph::kValue); |
| 1775 return replacement; | 1791 return replacement; |
| 1776 } | 1792 } |
| 1777 } | 1793 } |
| (...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2349 FlowGraph::kValue); | 2365 FlowGraph::kValue); |
| 2350 return replacement; | 2366 return replacement; |
| 2351 } | 2367 } |
| 2352 | 2368 |
| 2353 return this; | 2369 return this; |
| 2354 } | 2370 } |
| 2355 | 2371 |
| 2356 | 2372 |
| 2357 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) { | 2373 Definition* BooleanNegateInstr::Canonicalize(FlowGraph* flow_graph) { |
| 2358 Definition* defn = value()->definition(); | 2374 Definition* defn = value()->definition(); |
| 2359 if (defn->IsComparison() && defn->HasOnlyUse(value())) { | 2375 if (defn->IsComparison() && |
| 2360 // Comparisons always have a bool result. | 2376 defn->HasOnlyUse(value()) && |
| 2361 ASSERT(value()->definition()->Type()->ToCid() == kBoolCid); | 2377 defn->Type()->ToCid() == kBoolCid) { |
| 2362 defn->AsComparison()->NegateComparison(); | 2378 defn->AsComparison()->NegateComparison(); |
| 2363 return defn; | 2379 return defn; |
| 2364 } | 2380 } |
| 2365 return this; | 2381 return this; |
| 2366 } | 2382 } |
| 2367 | 2383 |
| 2368 | 2384 |
| 2369 static bool MayBeBoxableNumber(intptr_t cid) { | 2385 static bool MayBeBoxableNumber(intptr_t cid) { |
| 2370 return (cid == kDynamicCid) || | 2386 return (cid == kDynamicCid) || |
| 2371 (cid == kMintCid) || | 2387 (cid == kMintCid) || |
| 2372 (cid == kBigintCid) || | 2388 (cid == kBigintCid) || |
| 2373 (cid == kDoubleCid); | 2389 (cid == kDoubleCid); |
| 2374 } | 2390 } |
| 2375 | 2391 |
| 2376 | 2392 |
| 2377 static bool MaybeNumber(CompileType* type) { | 2393 static bool MaybeNumber(CompileType* type) { |
| 2378 ASSERT(Type::Handle(Type::Number()).IsMoreSpecificThan( | 2394 ASSERT(Type::Handle(Type::Number()).IsMoreSpecificThan( |
| 2379 Type::Handle(Type::Number()), NULL, NULL, Heap::kOld)); | 2395 Type::Handle(Type::Number()), NULL, NULL, Heap::kOld)); |
| 2380 return type->ToAbstractType()->IsDynamicType() | 2396 return type->ToAbstractType()->IsDynamicType() |
| 2381 || type->ToAbstractType()->IsObjectType() | 2397 || type->ToAbstractType()->IsObjectType() |
| 2382 || type->ToAbstractType()->IsTypeParameter() | 2398 || type->ToAbstractType()->IsTypeParameter() |
| 2383 || type->IsMoreSpecificThan(Type::Handle(Type::Number())); | 2399 || type->IsMoreSpecificThan(Type::Handle(Type::Number())); |
| 2384 } | 2400 } |
| 2385 | 2401 |
| 2386 | 2402 |
| 2387 // Returns a replacement for a strict comparison and signals if the result has | 2403 // Returns a replacement for a strict comparison and signals if the result has |
| 2388 // to be negated. | 2404 // to be negated. |
| 2389 static Definition* CanonicalizeStrictCompare(StrictCompareInstr* compare, | 2405 static Definition* CanonicalizeStrictCompare(StrictCompareInstr* compare, |
| 2390 bool* negated) { | 2406 bool* negated, |
| 2407 bool is_branch) { |
| 2391 // Use propagated cid and type information to eliminate number checks. | 2408 // Use propagated cid and type information to eliminate number checks. |
| 2392 // If one of the inputs is not a boxable number (Mint, Double, Bigint), or | 2409 // If one of the inputs is not a boxable number (Mint, Double, Bigint), or |
| 2393 // is not a subtype of num, no need for number checks. | 2410 // is not a subtype of num, no need for number checks. |
| 2394 if (compare->needs_number_check()) { | 2411 if (compare->needs_number_check()) { |
| 2395 if (!MayBeBoxableNumber(compare->left()->Type()->ToCid()) || | 2412 if (!MayBeBoxableNumber(compare->left()->Type()->ToCid()) || |
| 2396 !MayBeBoxableNumber(compare->right()->Type()->ToCid())) { | 2413 !MayBeBoxableNumber(compare->right()->Type()->ToCid())) { |
| 2397 compare->set_needs_number_check(false); | 2414 compare->set_needs_number_check(false); |
| 2398 } else if (!MaybeNumber(compare->left()->Type()) || | 2415 } else if (!MaybeNumber(compare->left()->Type()) || |
| 2399 !MaybeNumber(compare->right()->Type())) { | 2416 !MaybeNumber(compare->right()->Type())) { |
| 2400 compare->set_needs_number_check(false); | 2417 compare->set_needs_number_check(false); |
| 2401 } | 2418 } |
| 2402 } | 2419 } |
| 2403 | |
| 2404 *negated = false; | 2420 *negated = false; |
| 2405 PassiveObject& constant = PassiveObject::Handle(); | 2421 PassiveObject& constant = PassiveObject::Handle(); |
| 2406 Value* other = NULL; | 2422 Value* other = NULL; |
| 2407 if (compare->right()->BindsToConstant()) { | 2423 if (compare->right()->BindsToConstant()) { |
| 2408 constant = compare->right()->BoundConstant().raw(); | 2424 constant = compare->right()->BoundConstant().raw(); |
| 2409 other = compare->left(); | 2425 other = compare->left(); |
| 2410 } else if (compare->left()->BindsToConstant()) { | 2426 } else if (compare->left()->BindsToConstant()) { |
| 2411 constant = compare->left()->BoundConstant().raw(); | 2427 constant = compare->left()->BoundConstant().raw(); |
| 2412 other = compare->right(); | 2428 other = compare->right(); |
| 2413 } else { | 2429 } else { |
| 2414 return compare; | 2430 return compare; |
| 2415 } | 2431 } |
| 2416 | 2432 |
| 2433 const bool can_merge = is_branch || (other->Type()->ToCid() == kBoolCid); |
| 2417 Definition* other_defn = other->definition(); | 2434 Definition* other_defn = other->definition(); |
| 2418 Token::Kind kind = compare->kind(); | 2435 Token::Kind kind = compare->kind(); |
| 2419 // Handle e === true. | 2436 // Handle e === true. |
| 2420 if ((kind == Token::kEQ_STRICT) && | 2437 if ((kind == Token::kEQ_STRICT) && |
| 2421 (constant.raw() == Bool::True().raw()) && | 2438 (constant.raw() == Bool::True().raw()) && |
| 2422 (other->Type()->ToCid() == kBoolCid)) { | 2439 can_merge) { |
| 2423 return other_defn; | 2440 return other_defn; |
| 2424 } | 2441 } |
| 2425 // Handle e !== false. | 2442 // Handle e !== false. |
| 2426 if ((kind == Token::kNE_STRICT) && | 2443 if ((kind == Token::kNE_STRICT) && |
| 2427 (constant.raw() == Bool::False().raw()) && | 2444 (constant.raw() == Bool::False().raw()) && |
| 2428 (other->Type()->ToCid() == kBoolCid)) { | 2445 can_merge) { |
| 2429 return other_defn; | 2446 return other_defn; |
| 2430 } | 2447 } |
| 2431 // Handle e !== true. | 2448 // Handle e !== true. |
| 2432 if ((kind == Token::kNE_STRICT) && | 2449 if ((kind == Token::kNE_STRICT) && |
| 2433 (constant.raw() == Bool::True().raw()) && | 2450 (constant.raw() == Bool::True().raw()) && |
| 2434 other_defn->IsComparison() && | 2451 other_defn->IsComparison() && |
| 2435 (other->Type()->ToCid() == kBoolCid) && | 2452 can_merge && |
| 2436 other_defn->HasOnlyUse(other)) { | 2453 other_defn->HasOnlyUse(other)) { |
| 2437 *negated = true; | 2454 *negated = true; |
| 2438 return other_defn; | 2455 return other_defn; |
| 2439 } | 2456 } |
| 2440 // Handle e === false. | 2457 // Handle e === false. |
| 2441 if ((kind == Token::kEQ_STRICT) && | 2458 if ((kind == Token::kEQ_STRICT) && |
| 2442 (constant.raw() == Bool::False().raw()) && | 2459 (constant.raw() == Bool::False().raw()) && |
| 2443 other_defn->IsComparison() && | 2460 other_defn->IsComparison() && |
| 2444 (other->Type()->ToCid() == kBoolCid) && | 2461 can_merge && |
| 2445 other_defn->HasOnlyUse(other)) { | 2462 other_defn->HasOnlyUse(other)) { |
| 2446 *negated = true; | 2463 *negated = true; |
| 2447 return other_defn; | 2464 return other_defn; |
| 2448 } | 2465 } |
| 2449 return compare; | 2466 return compare; |
| 2450 } | 2467 } |
| 2451 | 2468 |
| 2452 | 2469 |
| 2453 static bool BindsToGivenConstant(Value* v, intptr_t expected) { | 2470 static bool BindsToGivenConstant(Value* v, intptr_t expected) { |
| 2454 return v->BindsToConstant() && | 2471 return v->BindsToConstant() && |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2494 return false; | 2511 return false; |
| 2495 } | 2512 } |
| 2496 | 2513 |
| 2497 | 2514 |
| 2498 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) { | 2515 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) { |
| 2499 Zone* zone = flow_graph->zone(); | 2516 Zone* zone = flow_graph->zone(); |
| 2500 // Only handle strict-compares. | 2517 // Only handle strict-compares. |
| 2501 if (comparison()->IsStrictCompare()) { | 2518 if (comparison()->IsStrictCompare()) { |
| 2502 bool negated = false; | 2519 bool negated = false; |
| 2503 Definition* replacement = | 2520 Definition* replacement = |
| 2504 CanonicalizeStrictCompare(comparison()->AsStrictCompare(), &negated); | 2521 CanonicalizeStrictCompare(comparison()->AsStrictCompare(), |
| 2522 &negated, /* is_branch = */ true); |
| 2505 if (replacement == comparison()) { | 2523 if (replacement == comparison()) { |
| 2506 return this; | 2524 return this; |
| 2507 } | 2525 } |
| 2508 ComparisonInstr* comp = replacement->AsComparison(); | 2526 ComparisonInstr* comp = replacement->AsComparison(); |
| 2509 if ((comp == NULL) || | 2527 if ((comp == NULL) || |
| 2510 comp->CanDeoptimize() || | 2528 comp->CanDeoptimize() || |
| 2511 comp->HasUnmatchedInputRepresentations()) { | 2529 comp->HasUnmatchedInputRepresentations()) { |
| 2512 return this; | 2530 return this; |
| 2513 } | 2531 } |
| 2514 | 2532 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2566 bit_and->RemoveFromGraph(); | 2584 bit_and->RemoveFromGraph(); |
| 2567 } | 2585 } |
| 2568 } | 2586 } |
| 2569 return this; | 2587 return this; |
| 2570 } | 2588 } |
| 2571 | 2589 |
| 2572 | 2590 |
| 2573 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) { | 2591 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) { |
| 2574 if (!HasUses()) return NULL; | 2592 if (!HasUses()) return NULL; |
| 2575 bool negated = false; | 2593 bool negated = false; |
| 2576 Definition* replacement = CanonicalizeStrictCompare(this, &negated); | 2594 Definition* replacement = CanonicalizeStrictCompare(this, &negated, |
| 2595 /* is_branch = */ false); |
| 2577 if (negated && replacement->IsComparison()) { | 2596 if (negated && replacement->IsComparison()) { |
| 2578 ASSERT(replacement != this); | 2597 ASSERT(replacement != this); |
| 2579 replacement->AsComparison()->NegateComparison(); | 2598 replacement->AsComparison()->NegateComparison(); |
| 2580 } | 2599 } |
| 2581 return replacement; | 2600 return replacement; |
| 2582 } | 2601 } |
| 2583 | 2602 |
| 2584 | 2603 |
| 2585 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) { | 2604 Instruction* CheckClassInstr::Canonicalize(FlowGraph* flow_graph) { |
| 2586 const intptr_t value_cid = value()->Type()->ToCid(); | 2605 const intptr_t value_cid = value()->Type()->ToCid(); |
| (...skipping 1349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3936 set_native_c_function(native_function); | 3955 set_native_c_function(native_function); |
| 3937 function().SetIsNativeAutoSetupScope(auto_setup_scope); | 3956 function().SetIsNativeAutoSetupScope(auto_setup_scope); |
| 3938 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); | 3957 Dart_NativeEntryResolver resolver = library.native_entry_resolver(); |
| 3939 bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver); | 3958 bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver); |
| 3940 set_is_bootstrap_native(is_bootstrap_native); | 3959 set_is_bootstrap_native(is_bootstrap_native); |
| 3941 } | 3960 } |
| 3942 | 3961 |
| 3943 #undef __ | 3962 #undef __ |
| 3944 | 3963 |
| 3945 } // namespace dart | 3964 } // namespace dart |
| OLD | NEW |