| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 if (!pointer->is_set()) { | 596 if (!pointer->is_set()) { |
| 597 HConstant* constant = | 597 HConstant* constant = |
| 598 new(zone()) HConstant(value, Representation::Integer32()); | 598 new(zone()) HConstant(value, Representation::Integer32()); |
| 599 constant->InsertAfter(GetConstantUndefined()); | 599 constant->InsertAfter(GetConstantUndefined()); |
| 600 pointer->set(constant); | 600 pointer->set(constant); |
| 601 } | 601 } |
| 602 return pointer->get(); | 602 return pointer->get(); |
| 603 } | 603 } |
| 604 | 604 |
| 605 | 605 |
| 606 HConstant* HGraph::GetConstantSmi(SetOncePointer<HConstant>* pointer, |
| 607 int32_t value) { |
| 608 if (!pointer->is_set()) { |
| 609 HConstant* constant = |
| 610 new(zone()) HConstant(Handle<Object>(Smi::FromInt(value), isolate()), |
| 611 Representation::Tagged()); |
| 612 constant->InsertAfter(GetConstantUndefined()); |
| 613 pointer->set(constant); |
| 614 } |
| 615 return pointer->get(); |
| 616 } |
| 617 |
| 618 |
| 606 HConstant* HGraph::GetConstant0() { | 619 HConstant* HGraph::GetConstant0() { |
| 607 return GetConstantInt32(&constant_0_, 0); | 620 return GetConstantInt32(&constant_0_, 0); |
| 608 } | 621 } |
| 609 | 622 |
| 610 | 623 |
| 611 HConstant* HGraph::GetConstant1() { | 624 HConstant* HGraph::GetConstant1() { |
| 612 return GetConstantInt32(&constant_1_, 1); | 625 return GetConstantInt32(&constant_1_, 1); |
| 613 } | 626 } |
| 614 | 627 |
| 615 | 628 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 631 constant->InsertAfter(GetConstantUndefined()); \ | 644 constant->InsertAfter(GetConstantUndefined()); \ |
| 632 constant_##name##_.set(constant); \ | 645 constant_##name##_.set(constant); \ |
| 633 } \ | 646 } \ |
| 634 return constant_##name##_.get(); \ | 647 return constant_##name##_.get(); \ |
| 635 } | 648 } |
| 636 | 649 |
| 637 | 650 |
| 638 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) | 651 DEFINE_GET_CONSTANT(True, true, HType::Boolean(), true) |
| 639 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) | 652 DEFINE_GET_CONSTANT(False, false, HType::Boolean(), false) |
| 640 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) | 653 DEFINE_GET_CONSTANT(Hole, the_hole, HType::Tagged(), false) |
| 654 DEFINE_GET_CONSTANT(Null, null, HType::Tagged(), false) |
| 655 |
| 656 |
| 657 HConstant* HGraph::GetConstantSmi0() { |
| 658 return GetConstantSmi(&constant_smi_0_, 0); |
| 659 } |
| 660 |
| 661 |
| 662 HConstant* HGraph::GetConstantSmi1() { |
| 663 return GetConstantSmi(&constant_smi_1_, 1); |
| 664 } |
| 665 |
| 641 | 666 |
| 642 #undef DEFINE_GET_CONSTANT | 667 #undef DEFINE_GET_CONSTANT |
| 643 | 668 |
| 644 | 669 |
| 645 HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder) | 670 HGraphBuilder::CheckBuilder::CheckBuilder(HGraphBuilder* builder) |
| 646 : builder_(builder), | 671 : builder_(builder), |
| 647 finished_(false) { | 672 finished_(false) { |
| 648 HEnvironment* env = builder->environment(); | 673 HEnvironment* env = builder->environment(); |
| 649 failure_block_ = builder->CreateBasicBlock(env->Copy()); | 674 failure_block_ = builder->CreateBasicBlock(env->Copy()); |
| 650 merge_block_ = builder->CreateBasicBlock(env->Copy()); | 675 merge_block_ = builder->CreateBasicBlock(env->Copy()); |
| (...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1726 key_constant, | 1751 key_constant, |
| 1727 value, | 1752 value, |
| 1728 kind)); | 1753 kind)); |
| 1729 } | 1754 } |
| 1730 } | 1755 } |
| 1731 | 1756 |
| 1732 return object; | 1757 return object; |
| 1733 } | 1758 } |
| 1734 | 1759 |
| 1735 | 1760 |
| 1761 void HGraphBuilder::BuildCompareNil( |
| 1762 HValue* value, |
| 1763 EqualityKind kind, |
| 1764 CompareNilICStub::Types types, |
| 1765 Handle<Map> map, |
| 1766 int position, |
| 1767 HIfContinuation* continuation) { |
| 1768 IfBuilder if_nil(this, position); |
| 1769 bool needs_or = false; |
| 1770 if ((types & CompareNilICStub::kCompareAgainstNull) != 0) { |
| 1771 if (needs_or) if_nil.Or(); |
| 1772 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); |
| 1773 needs_or = true; |
| 1774 } |
| 1775 if ((types & CompareNilICStub::kCompareAgainstUndefined) != 0) { |
| 1776 if (needs_or) if_nil.Or(); |
| 1777 if_nil.If<HCompareObjectEqAndBranch>(value, |
| 1778 graph()->GetConstantUndefined()); |
| 1779 needs_or = true; |
| 1780 } |
| 1781 // Handle either undetectable or monomorphic, not both. |
| 1782 ASSERT(((types & CompareNilICStub::kCompareAgainstUndetectable) == 0) || |
| 1783 ((types & CompareNilICStub::kCompareAgainstMonomorphicMap) == 0)); |
| 1784 if ((types & CompareNilICStub::kCompareAgainstUndetectable) != 0) { |
| 1785 if (needs_or) if_nil.Or(); |
| 1786 if_nil.If<HIsUndetectableAndBranch>(value); |
| 1787 } else { |
| 1788 if_nil.Then(); |
| 1789 if_nil.Else(); |
| 1790 if ((types & CompareNilICStub::kCompareAgainstMonomorphicMap) != 0) { |
| 1791 BuildCheckNonSmi(value); |
| 1792 BuildCheckMap(value, map); |
| 1793 } else { |
| 1794 if (kind == kNonStrictEquality) { |
| 1795 if_nil.Deopt(); |
| 1796 } |
| 1797 } |
| 1798 } |
| 1799 |
| 1800 if_nil.CaptureContinuation(continuation); |
| 1801 } |
| 1802 |
| 1803 |
| 1736 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, | 1804 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info, |
| 1737 TypeFeedbackOracle* oracle) | 1805 TypeFeedbackOracle* oracle) |
| 1738 : HGraphBuilder(info), | 1806 : HGraphBuilder(info), |
| 1739 function_state_(NULL), | 1807 function_state_(NULL), |
| 1740 initial_function_state_(this, info, oracle, NORMAL_RETURN), | 1808 initial_function_state_(this, info, oracle, NORMAL_RETURN), |
| 1741 ast_context_(NULL), | 1809 ast_context_(NULL), |
| 1742 break_scope_(NULL), | 1810 break_scope_(NULL), |
| 1743 inlined_count_(0), | 1811 inlined_count_(0), |
| 1744 globals_(10, info->zone()), | 1812 globals_(10, info->zone()), |
| 1745 inline_bailout_(false) { | 1813 inline_bailout_(false) { |
| (...skipping 8301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10047 HTypeof* typeof_expr, | 10115 HTypeof* typeof_expr, |
| 10048 Handle<String> check) { | 10116 Handle<String> check) { |
| 10049 // Note: The HTypeof itself is removed during canonicalization, if possible. | 10117 // Note: The HTypeof itself is removed during canonicalization, if possible. |
| 10050 HValue* value = typeof_expr->value(); | 10118 HValue* value = typeof_expr->value(); |
| 10051 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); | 10119 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); |
| 10052 instr->set_position(expr->position()); | 10120 instr->set_position(expr->position()); |
| 10053 return ast_context()->ReturnControl(instr, expr->id()); | 10121 return ast_context()->ReturnControl(instr, expr->id()); |
| 10054 } | 10122 } |
| 10055 | 10123 |
| 10056 | 10124 |
| 10057 static bool MatchLiteralCompareNil(HValue* left, | |
| 10058 Token::Value op, | |
| 10059 HValue* right, | |
| 10060 Handle<Object> nil, | |
| 10061 HValue** expr) { | |
| 10062 if (left->IsConstant() && | |
| 10063 HConstant::cast(left)->handle().is_identical_to(nil) && | |
| 10064 Token::IsEqualityOp(op)) { | |
| 10065 *expr = right; | |
| 10066 return true; | |
| 10067 } | |
| 10068 return false; | |
| 10069 } | |
| 10070 | |
| 10071 | |
| 10072 static bool MatchLiteralCompareTypeof(HValue* left, | 10125 static bool MatchLiteralCompareTypeof(HValue* left, |
| 10073 Token::Value op, | 10126 Token::Value op, |
| 10074 HValue* right, | 10127 HValue* right, |
| 10075 HTypeof** typeof_expr, | 10128 HTypeof** typeof_expr, |
| 10076 Handle<String>* check) { | 10129 Handle<String>* check) { |
| 10077 if (left->IsTypeof() && | 10130 if (left->IsTypeof() && |
| 10078 Token::IsEqualityOp(op) && | 10131 Token::IsEqualityOp(op) && |
| 10079 right->IsConstant() && | 10132 right->IsConstant() && |
| 10080 HConstant::cast(right)->handle()->IsString()) { | 10133 HConstant::cast(right)->handle()->IsString()) { |
| 10081 *typeof_expr = HTypeof::cast(left); | 10134 *typeof_expr = HTypeof::cast(left); |
| 10082 *check = Handle<String>::cast(HConstant::cast(right)->handle()); | 10135 *check = Handle<String>::cast(HConstant::cast(right)->handle()); |
| 10083 return true; | 10136 return true; |
| 10084 } | 10137 } |
| 10085 return false; | 10138 return false; |
| 10086 } | 10139 } |
| 10087 | 10140 |
| 10088 | 10141 |
| 10089 static bool IsLiteralCompareTypeof(HValue* left, | 10142 static bool IsLiteralCompareTypeof(HValue* left, |
| 10090 Token::Value op, | 10143 Token::Value op, |
| 10091 HValue* right, | 10144 HValue* right, |
| 10092 HTypeof** typeof_expr, | 10145 HTypeof** typeof_expr, |
| 10093 Handle<String>* check) { | 10146 Handle<String>* check) { |
| 10094 return MatchLiteralCompareTypeof(left, op, right, typeof_expr, check) || | 10147 return MatchLiteralCompareTypeof(left, op, right, typeof_expr, check) || |
| 10095 MatchLiteralCompareTypeof(right, op, left, typeof_expr, check); | 10148 MatchLiteralCompareTypeof(right, op, left, typeof_expr, check); |
| 10096 } | 10149 } |
| 10097 | 10150 |
| 10098 | 10151 |
| 10099 static bool IsLiteralCompareNil(HValue* left, | |
| 10100 Token::Value op, | |
| 10101 HValue* right, | |
| 10102 Handle<Object> nil, | |
| 10103 HValue** expr) { | |
| 10104 return MatchLiteralCompareNil(left, op, right, nil, expr) || | |
| 10105 MatchLiteralCompareNil(right, op, left, nil, expr); | |
| 10106 } | |
| 10107 | |
| 10108 | |
| 10109 static bool IsLiteralCompareBool(HValue* left, | 10152 static bool IsLiteralCompareBool(HValue* left, |
| 10110 Token::Value op, | 10153 Token::Value op, |
| 10111 HValue* right) { | 10154 HValue* right) { |
| 10112 return op == Token::EQ_STRICT && | 10155 return op == Token::EQ_STRICT && |
| 10113 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || | 10156 ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || |
| 10114 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); | 10157 (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); |
| 10115 } | 10158 } |
| 10116 | 10159 |
| 10117 | 10160 |
| 10118 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 10161 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10150 HValue* context = environment()->LookupContext(); | 10193 HValue* context = environment()->LookupContext(); |
| 10151 HValue* right = Pop(); | 10194 HValue* right = Pop(); |
| 10152 HValue* left = Pop(); | 10195 HValue* left = Pop(); |
| 10153 Token::Value op = expr->op(); | 10196 Token::Value op = expr->op(); |
| 10154 | 10197 |
| 10155 HTypeof* typeof_expr = NULL; | 10198 HTypeof* typeof_expr = NULL; |
| 10156 Handle<String> check; | 10199 Handle<String> check; |
| 10157 if (IsLiteralCompareTypeof(left, op, right, &typeof_expr, &check)) { | 10200 if (IsLiteralCompareTypeof(left, op, right, &typeof_expr, &check)) { |
| 10158 return HandleLiteralCompareTypeof(expr, typeof_expr, check); | 10201 return HandleLiteralCompareTypeof(expr, typeof_expr, check); |
| 10159 } | 10202 } |
| 10160 HValue* sub_expr = NULL; | 10203 |
| 10161 Factory* f = isolate()->factory(); | 10204 Expression* sub_expr = NULL; |
| 10162 if (IsLiteralCompareNil(left, op, right, f->undefined_value(), &sub_expr)) { | 10205 if (expr->IsLiteralCompareNull(&sub_expr)) { |
| 10163 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); | 10206 HValue* sub_expr_value = sub_expr == expr->left() ? left : right; |
| 10207 return HandleLiteralCompareNil(expr, sub_expr_value, kNullValue); |
| 10164 } | 10208 } |
| 10165 if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) { | 10209 if (expr->IsLiteralCompareUndefined(&sub_expr)) { |
| 10166 return HandleLiteralCompareNil(expr, sub_expr, kNullValue); | 10210 HValue* sub_expr_value = sub_expr == expr->left() ? left : right; |
| 10211 return HandleLiteralCompareNil(expr, sub_expr_value, kUndefinedValue); |
| 10167 } | 10212 } |
| 10168 if (IsLiteralCompareBool(left, op, right)) { | 10213 if (IsLiteralCompareBool(left, op, right)) { |
| 10169 HCompareObjectEqAndBranch* result = | 10214 HCompareObjectEqAndBranch* result = |
| 10170 new(zone()) HCompareObjectEqAndBranch(left, right); | 10215 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 10171 result->set_position(expr->position()); | 10216 result->set_position(expr->position()); |
| 10172 return ast_context()->ReturnControl(result, expr->id()); | 10217 return ast_context()->ReturnControl(result, expr->id()); |
| 10173 } | 10218 } |
| 10174 | 10219 |
| 10175 if (op == Token::INSTANCEOF) { | 10220 if (op == Token::INSTANCEOF) { |
| 10176 // Check to see if the rhs of the instanceof is a global function not | 10221 // Check to see if the rhs of the instanceof is a global function not |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10269 | 10314 |
| 10270 | 10315 |
| 10271 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 10316 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
| 10272 HValue* value, | 10317 HValue* value, |
| 10273 NilValue nil) { | 10318 NilValue nil) { |
| 10274 ASSERT(!HasStackOverflow()); | 10319 ASSERT(!HasStackOverflow()); |
| 10275 ASSERT(current_block() != NULL); | 10320 ASSERT(current_block() != NULL); |
| 10276 ASSERT(current_block()->HasPredecessor()); | 10321 ASSERT(current_block()->HasPredecessor()); |
| 10277 EqualityKind kind = | 10322 EqualityKind kind = |
| 10278 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; | 10323 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; |
| 10279 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); | 10324 HIfContinuation continuation; |
| 10280 instr->set_position(expr->position()); | 10325 TypeFeedbackId id = expr->CompareOperationFeedbackId(); |
| 10281 return ast_context()->ReturnControl(instr, expr->id()); | 10326 CompareNilICStub::Types types; |
| 10327 if (kind == kStrictEquality) { |
| 10328 if (nil == kNullValue) { |
| 10329 types = CompareNilICStub::kCompareAgainstNull; |
| 10330 } else { |
| 10331 types = CompareNilICStub::kCompareAgainstUndefined; |
| 10332 } |
| 10333 } else { |
| 10334 types = static_cast<CompareNilICStub::Types>( |
| 10335 oracle()->CompareNilTypes(id)); |
| 10336 if (types == 0) types = CompareNilICStub::kFullCompare; |
| 10337 } |
| 10338 Handle<Map> map_handle(oracle()->CompareNilMonomorphicReceiverType(id)); |
| 10339 BuildCompareNil(value, kind, types, map_handle, |
| 10340 expr->position(), &continuation); |
| 10341 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 10282 } | 10342 } |
| 10283 | 10343 |
| 10284 | 10344 |
| 10285 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 10345 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| 10286 // If we share optimized code between different closures, the | 10346 // If we share optimized code between different closures, the |
| 10287 // this-function is not a constant, except inside an inlined body. | 10347 // this-function is not a constant, except inside an inlined body. |
| 10288 if (function_state()->outer() != NULL) { | 10348 if (function_state()->outer() != NULL) { |
| 10289 return new(zone()) HConstant( | 10349 return new(zone()) HConstant( |
| 10290 function_state()->compilation_info()->closure(), | 10350 function_state()->compilation_info()->closure(), |
| 10291 Representation::Tagged()); | 10351 Representation::Tagged()); |
| (...skipping 1582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11874 } | 11934 } |
| 11875 } | 11935 } |
| 11876 | 11936 |
| 11877 #ifdef DEBUG | 11937 #ifdef DEBUG |
| 11878 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11938 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 11879 if (allocator_ != NULL) allocator_->Verify(); | 11939 if (allocator_ != NULL) allocator_->Verify(); |
| 11880 #endif | 11940 #endif |
| 11881 } | 11941 } |
| 11882 | 11942 |
| 11883 } } // namespace v8::internal | 11943 } } // namespace v8::internal |
| OLD | NEW |