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

Side by Side Diff: src/hydrogen.cc

Issue 146213004: A64: Synchronize with r16849. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 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 | « src/hydrogen.h ('k') | src/hydrogen-bce.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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 25 matching lines...) Expand all
36 #include "hydrogen-bce.h" 36 #include "hydrogen-bce.h"
37 #include "hydrogen-bch.h" 37 #include "hydrogen-bch.h"
38 #include "hydrogen-canonicalize.h" 38 #include "hydrogen-canonicalize.h"
39 #include "hydrogen-dce.h" 39 #include "hydrogen-dce.h"
40 #include "hydrogen-dehoist.h" 40 #include "hydrogen-dehoist.h"
41 #include "hydrogen-deoptimizing-mark.h" 41 #include "hydrogen-deoptimizing-mark.h"
42 #include "hydrogen-environment-liveness.h" 42 #include "hydrogen-environment-liveness.h"
43 #include "hydrogen-escape-analysis.h" 43 #include "hydrogen-escape-analysis.h"
44 #include "hydrogen-infer-representation.h" 44 #include "hydrogen-infer-representation.h"
45 #include "hydrogen-infer-types.h" 45 #include "hydrogen-infer-types.h"
46 #include "hydrogen-load-elimination.h"
46 #include "hydrogen-gvn.h" 47 #include "hydrogen-gvn.h"
47 #include "hydrogen-mark-deoptimize.h" 48 #include "hydrogen-mark-deoptimize.h"
48 #include "hydrogen-minus-zero.h" 49 #include "hydrogen-minus-zero.h"
49 #include "hydrogen-osr.h" 50 #include "hydrogen-osr.h"
50 #include "hydrogen-range-analysis.h" 51 #include "hydrogen-range-analysis.h"
51 #include "hydrogen-redundant-phi.h" 52 #include "hydrogen-redundant-phi.h"
52 #include "hydrogen-removable-simulates.h" 53 #include "hydrogen-removable-simulates.h"
53 #include "hydrogen-representation-changes.h" 54 #include "hydrogen-representation-changes.h"
54 #include "hydrogen-sce.h" 55 #include "hydrogen-sce.h"
55 #include "hydrogen-uint32-analysis.h" 56 #include "hydrogen-uint32-analysis.h"
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 finished_(false), 722 finished_(false),
722 deopt_then_(false), 723 deopt_then_(false),
723 deopt_else_(false), 724 deopt_else_(false),
724 did_then_(false), 725 did_then_(false),
725 did_else_(false), 726 did_else_(false),
726 did_and_(false), 727 did_and_(false),
727 did_or_(false), 728 did_or_(false),
728 captured_(false), 729 captured_(false),
729 needs_compare_(false), 730 needs_compare_(false),
730 first_true_block_(NULL), 731 first_true_block_(NULL),
732 last_true_block_(NULL),
731 first_false_block_(NULL), 733 first_false_block_(NULL),
732 split_edge_merge_block_(NULL), 734 split_edge_merge_block_(NULL),
733 merge_block_(NULL) { 735 merge_block_(NULL) {
734 continuation->Continue(&first_true_block_, 736 continuation->Continue(&first_true_block_,
735 &first_false_block_, 737 &first_false_block_,
736 &position_); 738 &position_);
737 } 739 }
738 740
739 741
740 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { 742 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
743 HControlInstruction* compare) {
741 if (split_edge_merge_block_ != NULL) { 744 if (split_edge_merge_block_ != NULL) {
742 HEnvironment* env = first_false_block_->last_environment(); 745 HEnvironment* env = first_false_block_->last_environment();
743 HBasicBlock* split_edge = 746 HBasicBlock* split_edge =
744 builder_->CreateBasicBlock(env->Copy()); 747 builder_->CreateBasicBlock(env->Copy());
745 if (did_or_) { 748 if (did_or_) {
746 compare->SetSuccessorAt(0, split_edge); 749 compare->SetSuccessorAt(0, split_edge);
747 compare->SetSuccessorAt(1, first_false_block_); 750 compare->SetSuccessorAt(1, first_false_block_);
748 } else { 751 } else {
749 compare->SetSuccessorAt(0, first_true_block_); 752 compare->SetSuccessorAt(0, first_true_block_);
750 compare->SetSuccessorAt(1, split_edge); 753 compare->SetSuccessorAt(1, split_edge);
751 } 754 }
752 split_edge->GotoNoSimulate(split_edge_merge_block_); 755 split_edge->GotoNoSimulate(split_edge_merge_block_);
753 } else { 756 } else {
754 compare->SetSuccessorAt(0, first_true_block_); 757 compare->SetSuccessorAt(0, first_true_block_);
755 compare->SetSuccessorAt(1, first_false_block_); 758 compare->SetSuccessorAt(1, first_false_block_);
756 } 759 }
757 builder_->current_block()->Finish(compare); 760 builder_->current_block()->Finish(compare);
758 needs_compare_ = false; 761 needs_compare_ = false;
762 return compare;
759 } 763 }
760 764
761 765
762 void HGraphBuilder::IfBuilder::Or() { 766 void HGraphBuilder::IfBuilder::Or() {
763 ASSERT(!did_and_); 767 ASSERT(!did_and_);
764 did_or_ = true; 768 did_or_ = true;
765 HEnvironment* env = first_false_block_->last_environment(); 769 HEnvironment* env = first_false_block_->last_environment();
766 if (split_edge_merge_block_ == NULL) { 770 if (split_edge_merge_block_ == NULL) {
767 split_edge_merge_block_ = 771 split_edge_merge_block_ =
768 builder_->CreateBasicBlock(env->Copy()); 772 builder_->CreateBasicBlock(env->Copy());
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 ASSERT(!finished_); 813 ASSERT(!finished_);
810 did_then_ = true; 814 did_then_ = true;
811 if (needs_compare_) { 815 if (needs_compare_) {
812 // Handle if's without any expressions, they jump directly to the "else" 816 // Handle if's without any expressions, they jump directly to the "else"
813 // branch. However, we must pretend that the "then" branch is reachable, 817 // branch. However, we must pretend that the "then" branch is reachable,
814 // so that the graph builder visits it and sees any live range extending 818 // so that the graph builder visits it and sees any live range extending
815 // constructs within it. 819 // constructs within it.
816 HConstant* constant_false = builder_->graph()->GetConstantFalse(); 820 HConstant* constant_false = builder_->graph()->GetConstantFalse();
817 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); 821 ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
818 boolean_type.Add(ToBooleanStub::BOOLEAN); 822 boolean_type.Add(ToBooleanStub::BOOLEAN);
819 HBranch* branch = 823 HBranch* branch = builder()->New<HBranch>(
820 new(zone()) HBranch(constant_false, boolean_type, first_true_block_, 824 constant_false, boolean_type, first_true_block_, first_false_block_);
821 first_false_block_);
822 builder_->current_block()->Finish(branch); 825 builder_->current_block()->Finish(branch);
823 } 826 }
824 builder_->set_current_block(first_true_block_); 827 builder_->set_current_block(first_true_block_);
825 } 828 }
826 829
827 830
828 void HGraphBuilder::IfBuilder::Else() { 831 void HGraphBuilder::IfBuilder::Else() {
829 ASSERT(did_then_); 832 ASSERT(did_then_);
830 ASSERT(!captured_); 833 ASSERT(!captured_);
831 ASSERT(!finished_); 834 ASSERT(!finished_);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 HEnvironment* body_env = env->Copy(); 946 HEnvironment* body_env = env->Copy();
944 HEnvironment* exit_env = env->Copy(); 947 HEnvironment* exit_env = env->Copy();
945 // Remove the phi from the expression stack 948 // Remove the phi from the expression stack
946 body_env->Pop(); 949 body_env->Pop();
947 exit_env->Pop(); 950 exit_env->Pop();
948 body_block_ = builder_->CreateBasicBlock(body_env); 951 body_block_ = builder_->CreateBasicBlock(body_env);
949 exit_block_ = builder_->CreateBasicBlock(exit_env); 952 exit_block_ = builder_->CreateBasicBlock(exit_env);
950 953
951 builder_->set_current_block(header_block_); 954 builder_->set_current_block(header_block_);
952 env->Pop(); 955 env->Pop();
953 HCompareNumericAndBranch* compare = 956 builder_->current_block()->Finish(builder_->New<HCompareNumericAndBranch>(
954 new(zone()) HCompareNumericAndBranch(phi_, terminating, token); 957 phi_, terminating, token, body_block_, exit_block_));
955 compare->SetSuccessorAt(0, body_block_);
956 compare->SetSuccessorAt(1, exit_block_);
957 builder_->current_block()->Finish(compare);
958 958
959 builder_->set_current_block(body_block_); 959 builder_->set_current_block(body_block_);
960 if (direction_ == kPreIncrement || direction_ == kPreDecrement) { 960 if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
961 HValue* one = builder_->graph()->GetConstant1(); 961 HValue* one = builder_->graph()->GetConstant1();
962 if (direction_ == kPreIncrement) { 962 if (direction_ == kPreIncrement) {
963 increment_ = HAdd::New(zone(), context_, phi_, one); 963 increment_ = HAdd::New(zone(), context_, phi_, one);
964 } else { 964 } else {
965 increment_ = HSub::New(zone(), context_, phi_, one); 965 increment_ = HSub::New(zone(), context_, phi_, one);
966 } 966 }
967 increment_->ClearFlag(HValue::kCanOverflow); 967 increment_->ClearFlag(HValue::kCanOverflow);
(...skipping 1798 matching lines...) Expand 10 before | Expand all | Expand 10 after
2766 // connects a branch node to a join node. We conservatively ensure that 2766 // connects a branch node to a join node. We conservatively ensure that
2767 // property by always adding an empty block on the outgoing edges of this 2767 // property by always adding an empty block on the outgoing edges of this
2768 // branch. 2768 // branch.
2769 HOptimizedGraphBuilder* builder = owner(); 2769 HOptimizedGraphBuilder* builder = owner();
2770 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { 2770 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
2771 builder->Bailout(kArgumentsObjectValueInATestContext); 2771 builder->Bailout(kArgumentsObjectValueInATestContext);
2772 } 2772 }
2773 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2773 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2774 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2774 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2775 ToBooleanStub::Types expected(condition()->to_boolean_types()); 2775 ToBooleanStub::Types expected(condition()->to_boolean_types());
2776 HBranch* test = new(zone()) HBranch(value, expected, empty_true, empty_false); 2776 builder->current_block()->Finish(builder->New<HBranch>(
2777 builder->current_block()->Finish(test); 2777 value, expected, empty_true, empty_false));
2778 2778
2779 empty_true->Goto(if_true(), builder->function_state()); 2779 empty_true->Goto(if_true(), builder->function_state());
2780 empty_false->Goto(if_false(), builder->function_state()); 2780 empty_false->Goto(if_false(), builder->function_state());
2781 builder->set_current_block(NULL); 2781 builder->set_current_block(NULL);
2782 } 2782 }
2783 2783
2784 2784
2785 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts. 2785 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
2786 #define CHECK_BAILOUT(call) \ 2786 #define CHECK_BAILOUT(call) \
2787 do { \ 2787 do { \
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
2966 if (!CheckArgumentsPhiUses()) { 2966 if (!CheckArgumentsPhiUses()) {
2967 *bailout_reason = kUnsupportedPhiUseOfArguments; 2967 *bailout_reason = kUnsupportedPhiUseOfArguments;
2968 return false; 2968 return false;
2969 } 2969 }
2970 2970
2971 // Remove dead code and phis 2971 // Remove dead code and phis
2972 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); 2972 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
2973 2973
2974 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); 2974 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
2975 2975
2976 if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
2977
2976 CollectPhis(); 2978 CollectPhis();
2977 2979
2978 if (has_osr()) osr()->FinishOsrValues(); 2980 if (has_osr()) osr()->FinishOsrValues();
2979 2981
2980 Run<HInferRepresentationPhase>(); 2982 Run<HInferRepresentationPhase>();
2981 2983
2982 // Remove HSimulate instructions that have turned out not to be needed 2984 // Remove HSimulate instructions that have turned out not to be needed
2983 // after all by folding them into the following HSimulate. 2985 // after all by folding them into the following HSimulate.
2984 // This must happen after inferring representations. 2986 // This must happen after inferring representations.
2985 Run<HMergeRemovableSimulatesPhase>(); 2987 Run<HMergeRemovableSimulatesPhase>();
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
3366 CHECK_ALIVE(VisitForValue(stmt->tag())); 3368 CHECK_ALIVE(VisitForValue(stmt->tag()));
3367 Add<HSimulate>(stmt->EntryId()); 3369 Add<HSimulate>(stmt->EntryId());
3368 HValue* tag_value = Pop(); 3370 HValue* tag_value = Pop();
3369 HBasicBlock* first_test_block = current_block(); 3371 HBasicBlock* first_test_block = current_block();
3370 3372
3371 HUnaryControlInstruction* string_check = NULL; 3373 HUnaryControlInstruction* string_check = NULL;
3372 HBasicBlock* not_string_block = NULL; 3374 HBasicBlock* not_string_block = NULL;
3373 3375
3374 // Test switch's tag value if all clauses are string literals 3376 // Test switch's tag value if all clauses are string literals
3375 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { 3377 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) {
3376 string_check = new(zone()) HIsStringAndBranch(tag_value);
3377 first_test_block = graph()->CreateBasicBlock(); 3378 first_test_block = graph()->CreateBasicBlock();
3378 not_string_block = graph()->CreateBasicBlock(); 3379 not_string_block = graph()->CreateBasicBlock();
3379 3380 string_check = New<HIsStringAndBranch>(
3380 string_check->SetSuccessorAt(0, first_test_block); 3381 tag_value, first_test_block, not_string_block);
3381 string_check->SetSuccessorAt(1, not_string_block);
3382 current_block()->Finish(string_check); 3382 current_block()->Finish(string_check);
3383 3383
3384 set_current_block(first_test_block); 3384 set_current_block(first_test_block);
3385 } 3385 }
3386 3386
3387 // 1. Build all the tests, with dangling true branches 3387 // 1. Build all the tests, with dangling true branches
3388 BailoutId default_id = BailoutId::None(); 3388 BailoutId default_id = BailoutId::None();
3389 for (int i = 0; i < clause_count; ++i) { 3389 for (int i = 0; i < clause_count; ++i) {
3390 CaseClause* clause = clauses->at(i); 3390 CaseClause* clause = clauses->at(i);
3391 if (clause->is_default()) { 3391 if (clause->is_default()) {
3392 default_id = clause->EntryId(); 3392 default_id = clause->EntryId();
3393 continue; 3393 continue;
3394 } 3394 }
3395 3395
3396 // Generate a compare and branch. 3396 // Generate a compare and branch.
3397 CHECK_ALIVE(VisitForValue(clause->label())); 3397 CHECK_ALIVE(VisitForValue(clause->label()));
3398 HValue* label_value = Pop(); 3398 HValue* label_value = Pop();
3399 3399
3400 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 3400 HBasicBlock* next_test_block = graph()->CreateBasicBlock();
3401 HBasicBlock* body_block = graph()->CreateBasicBlock(); 3401 HBasicBlock* body_block = graph()->CreateBasicBlock();
3402 3402
3403 HControlInstruction* compare; 3403 HControlInstruction* compare;
3404 3404
3405 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { 3405 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) {
3406 if (!clause->compare_type()->Is(Type::Smi())) { 3406 if (!clause->compare_type()->Is(Type::Smi())) {
3407 Add<HDeoptimize>("Non-smi switch type", Deoptimizer::SOFT); 3407 Add<HDeoptimize>("Non-smi switch type", Deoptimizer::SOFT);
3408 } 3408 }
3409 3409
3410 HCompareNumericAndBranch* compare_ = 3410 HCompareNumericAndBranch* compare_ =
3411 new(zone()) HCompareNumericAndBranch(tag_value, 3411 New<HCompareNumericAndBranch>(tag_value,
3412 label_value, 3412 label_value,
3413 Token::EQ_STRICT); 3413 Token::EQ_STRICT);
3414 compare_->set_observed_input_representation( 3414 compare_->set_observed_input_representation(
3415 Representation::Smi(), Representation::Smi()); 3415 Representation::Smi(), Representation::Smi());
3416 compare = compare_; 3416 compare = compare_;
3417 } else { 3417 } else {
3418 compare = new(zone()) HStringCompareAndBranch(context, tag_value, 3418 compare = new(zone()) HStringCompareAndBranch(context, tag_value,
3419 label_value, 3419 label_value,
3420 Token::EQ_STRICT); 3420 Token::EQ_STRICT);
3421 } 3421 }
3422 3422
3423 compare->SetSuccessorAt(0, body_block); 3423 compare->SetSuccessorAt(0, body_block);
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
3687 HForInCacheArray::cast(array)->set_index_cache( 3687 HForInCacheArray::cast(array)->set_index_cache(
3688 HForInCacheArray::cast(index_cache)); 3688 HForInCacheArray::cast(index_cache));
3689 3689
3690 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt); 3690 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt);
3691 3691
3692 HValue* index = environment()->ExpressionStackAt(0); 3692 HValue* index = environment()->ExpressionStackAt(0);
3693 HValue* limit = environment()->ExpressionStackAt(1); 3693 HValue* limit = environment()->ExpressionStackAt(1);
3694 3694
3695 // Check that we still have more keys. 3695 // Check that we still have more keys.
3696 HCompareNumericAndBranch* compare_index = 3696 HCompareNumericAndBranch* compare_index =
3697 new(zone()) HCompareNumericAndBranch(index, limit, Token::LT); 3697 New<HCompareNumericAndBranch>(index, limit, Token::LT);
3698 compare_index->set_observed_input_representation( 3698 compare_index->set_observed_input_representation(
3699 Representation::Smi(), Representation::Smi()); 3699 Representation::Smi(), Representation::Smi());
3700 3700
3701 HBasicBlock* loop_body = graph()->CreateBasicBlock(); 3701 HBasicBlock* loop_body = graph()->CreateBasicBlock();
3702 HBasicBlock* loop_successor = graph()->CreateBasicBlock(); 3702 HBasicBlock* loop_successor = graph()->CreateBasicBlock();
3703 3703
3704 compare_index->SetSuccessorAt(0, loop_body); 3704 compare_index->SetSuccessorAt(0, loop_body);
3705 compare_index->SetSuccessorAt(1, loop_successor); 3705 compare_index->SetSuccessorAt(1, loop_successor);
3706 current_block()->Finish(compare_index); 3706 current_block()->Finish(compare_index);
3707 3707
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
4057 *accessors = Handle<AccessorPair>::cast(callback); 4057 *accessors = Handle<AccessorPair>::cast(callback);
4058 *holder = Handle<JSObject>(lookup.holder()); 4058 *holder = Handle<JSObject>(lookup.holder());
4059 return true; 4059 return true;
4060 } 4060 }
4061 4061
4062 // We haven't found a JavaScript accessor anywhere. 4062 // We haven't found a JavaScript accessor anywhere.
4063 return false; 4063 return false;
4064 } 4064 }
4065 4065
4066 4066
4067 static bool LookupGetter(Handle<Map> map,
4068 Handle<String> name,
4069 Handle<JSFunction>* getter,
4070 Handle<JSObject>* holder) {
4071 Handle<AccessorPair> accessors;
4072 if (LookupAccessorPair(map, name, &accessors, holder) &&
4073 accessors->getter()->IsJSFunction()) {
4074 *getter = Handle<JSFunction>(JSFunction::cast(accessors->getter()));
4075 return true;
4076 }
4077 return false;
4078 }
4079
4080
4081 static bool LookupSetter(Handle<Map> map, 4067 static bool LookupSetter(Handle<Map> map,
4082 Handle<String> name, 4068 Handle<String> name,
4083 Handle<JSFunction>* setter, 4069 Handle<JSFunction>* setter,
4084 Handle<JSObject>* holder) { 4070 Handle<JSObject>* holder) {
4085 Handle<AccessorPair> accessors; 4071 Handle<AccessorPair> accessors;
4086 if (LookupAccessorPair(map, name, &accessors, holder) && 4072 if (LookupAccessorPair(map, name, &accessors, holder) &&
4087 accessors->setter()->IsJSFunction()) { 4073 accessors->setter()->IsJSFunction()) {
4088 *setter = Handle<JSFunction>(JSFunction::cast(accessors->setter())); 4074 *setter = Handle<JSFunction>(JSFunction::cast(accessors->setter()));
4089 return true; 4075 return true;
4090 } 4076 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
4185 int flags = expr->fast_elements() 4171 int flags = expr->fast_elements()
4186 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; 4172 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags;
4187 flags |= expr->has_function() 4173 flags |= expr->has_function()
4188 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; 4174 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags;
4189 4175
4190 Add<HPushArgument>(Add<HConstant>(closure_literals)); 4176 Add<HPushArgument>(Add<HConstant>(closure_literals));
4191 Add<HPushArgument>(Add<HConstant>(literal_index)); 4177 Add<HPushArgument>(Add<HConstant>(literal_index));
4192 Add<HPushArgument>(Add<HConstant>(constant_properties)); 4178 Add<HPushArgument>(Add<HConstant>(constant_properties));
4193 Add<HPushArgument>(Add<HConstant>(flags)); 4179 Add<HPushArgument>(Add<HConstant>(flags));
4194 4180
4195 Runtime::FunctionId function_id = 4181 Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
4196 (expr->depth() > 1 || expr->may_store_doubles())
4197 ? Runtime::kCreateObjectLiteral : Runtime::kCreateObjectLiteralShallow;
4198 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), 4182 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
4199 Runtime::FunctionForId(function_id), 4183 Runtime::FunctionForId(function_id),
4200 4); 4184 4);
4201 } 4185 }
4202 4186
4203 // The object is expected in the bailout environment during computation 4187 // The object is expected in the bailout environment during computation
4204 // of the property values and is the value of the entire expression. 4188 // of the property values and is the value of the entire expression.
4205 Push(literal); 4189 Push(literal);
4206 4190
4207 expr->CalculateEmitStore(zone()); 4191 expr->CalculateEmitStore(zone());
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
4538 if (ComputeLoadStoreField(map, name, &lookup, true)) { 4522 if (ComputeLoadStoreField(map, name, &lookup, true)) {
4539 HCheckMaps* checked_object = AddCheckMap(object, map); 4523 HCheckMaps* checked_object = AddCheckMap(object, map);
4540 return BuildStoreNamedField(checked_object, name, value, map, &lookup); 4524 return BuildStoreNamedField(checked_object, name, value, map, &lookup);
4541 } 4525 }
4542 4526
4543 // No luck, do a generic store. 4527 // No luck, do a generic store.
4544 return BuildStoreNamedGeneric(object, name, value); 4528 return BuildStoreNamedGeneric(object, name, value);
4545 } 4529 }
4546 4530
4547 4531
4548 static bool CanLoadPropertyFromPrototype(Handle<Map> map, 4532 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatibleForLoad(
4549 Handle<Name> name, 4533 PropertyAccessInfo* info) {
4550 LookupResult* lookup) { 4534 if (!CanInlinePropertyAccess(*map_)) return false;
4551 if (!CanInlinePropertyAccess(*map)) return false; 4535
4552 map->LookupDescriptor(NULL, *name, lookup); 4536 if (!LookupDescriptor()) return false;
4553 if (lookup->IsFound()) return false; 4537
4538 if (!lookup_.IsFound()) {
4539 return (!info->lookup_.IsFound() || !info->holder_.is_null()) &&
4540 map_->prototype() == info->map_->prototype();
4541 }
4542
4543 if (lookup_.IsPropertyCallbacks()) {
4544 return accessor_.is_identical_to(info->accessor_);
4545 }
4546
4547 if (lookup_.IsConstant()) {
4548 return constant_.is_identical_to(info->constant_);
4549 }
4550
4551 ASSERT(lookup_.IsField());
4552 if (!info->lookup_.IsField()) return false;
4553
4554 Representation r = access_.representation();
4555 if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
4556 if (info->access_.offset() != access_.offset()) return false;
4557 if (info->access_.IsInobject() != access_.IsInobject()) return false;
4558 info->GeneralizeRepresentation(r);
4554 return true; 4559 return true;
4555 } 4560 }
4556 4561
4557 4562
4558 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( 4563 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
4559 HValue* object, 4564 map_->LookupDescriptor(NULL, *name_, &lookup_);
4560 SmallMapList* types, 4565 return LoadResult(map_);
4561 Handle<String> name) {
4562 // Use monomorphic load if property lookup results in the same field index
4563 // for all maps. Requires special map check on the set of all handled maps.
4564 if (types->length() > kMaxLoadPolymorphism) return NULL;
4565
4566 LookupResult lookup(isolate());
4567 int count;
4568 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
4569 for (count = 0; count < types->length(); ++count) {
4570 Handle<Map> map = types->at(count);
4571 if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
4572
4573 HObjectAccess new_access = HObjectAccess::ForField(map, &lookup, name);
4574
4575 if (count == 0) {
4576 // First time through the loop; set access and representation.
4577 access = new_access;
4578 } else if (!access.representation().IsCompatibleForLoad(
4579 new_access.representation())) {
4580 // Representations did not match.
4581 break;
4582 } else if (access.offset() != new_access.offset()) {
4583 // Offsets did not match.
4584 break;
4585 } else if (access.IsInobject() != new_access.IsInobject()) {
4586 // In-objectness did not match.
4587 break;
4588 }
4589 access = access.WithRepresentation(
4590 access.representation().generalize(new_access.representation()));
4591 }
4592
4593 if (count == types->length()) {
4594 // Everything matched; can use monomorphic load.
4595 BuildCheckHeapObject(object);
4596 HCheckMaps* checked_object = Add<HCheckMaps>(object, types);
4597 return BuildLoadNamedField(checked_object, access);
4598 }
4599
4600 if (count != 0) return NULL;
4601
4602 // Second chance: the property is on the prototype and all maps have the
4603 // same prototype.
4604 Handle<Map> map(types->at(0));
4605 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL;
4606
4607 Handle<Object> prototype(map->prototype(), isolate());
4608 for (count = 1; count < types->length(); ++count) {
4609 Handle<Map> test_map(types->at(count));
4610 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL;
4611 if (test_map->prototype() != *prototype) return NULL;
4612 }
4613
4614 LookupInPrototypes(map, name, &lookup);
4615 if (!lookup.IsField()) return NULL;
4616
4617 BuildCheckHeapObject(object);
4618 Add<HCheckMaps>(object, types);
4619
4620 Handle<JSObject> holder(lookup.holder());
4621 Handle<Map> holder_map(holder->map());
4622 HValue* checked_holder = BuildCheckPrototypeMaps(
4623 Handle<JSObject>::cast(prototype), holder);
4624 return BuildLoadNamedField(checked_holder,
4625 HObjectAccess::ForField(holder_map, &lookup, name));
4626 } 4566 }
4627 4567
4628 4568
4629 // Returns true if an instance of this map can never find a property with this 4569 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
4630 // name in its prototype chain. This means all prototypes up to the top are 4570 if (lookup_.IsField()) {
4631 // fast and don't have the name in them. It would be good if we could optimize 4571 access_ = HObjectAccess::ForField(map, &lookup_, name_);
4632 // polymorphic loads where the property is sometimes found in the prototype 4572 } else if (lookup_.IsPropertyCallbacks()) {
4633 // chain. 4573 Handle<Object> callback(lookup_.GetValueFromMap(*map), isolate());
4634 static bool PrototypeChainCanNeverResolve( 4574 if (!callback->IsAccessorPair()) return false;
4635 Handle<Map> map, Handle<String> name) { 4575 Object* getter = Handle<AccessorPair>::cast(callback)->getter();
4636 Isolate* isolate = map->GetIsolate(); 4576 if (!getter->IsJSFunction()) return false;
4637 Object* current = map->prototype(); 4577 accessor_ = handle(JSFunction::cast(getter));
4638 while (current != isolate->heap()->null_value()) { 4578 } else if (lookup_.IsConstant()) {
4639 if (current->IsJSGlobalProxy() || 4579 constant_ = handle(lookup_.GetConstantFromMap(*map), isolate());
4640 current->IsGlobalObject() || 4580 }
4641 !current->IsJSObject() || 4581
4642 !CanInlinePropertyAccess(JSObject::cast(current)->map()) || 4582 return true;
4643 JSObject::cast(current)->IsAccessCheckNeeded()) { 4583 }
4584
4585
4586 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
4587 Handle<Map> map = map_;
4588 while (map->prototype()->IsJSObject()) {
4589 holder_ = handle(JSObject::cast(map->prototype()));
4590 map = Handle<Map>(holder_->map());
4591 if (!CanInlinePropertyAccess(*map)) {
4592 lookup_.NotFound();
4644 return false; 4593 return false;
4645 } 4594 }
4595 map->LookupDescriptor(*holder_, *name_, &lookup_);
4596 if (lookup_.IsFound()) return LoadResult(map);
4597 }
4598 lookup_.NotFound();
4599 return true;
4600 }
4646 4601
4647 LookupResult lookup(isolate); 4602
4648 Map* map = JSObject::cast(current)->map(); 4603 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() {
4649 map->LookupDescriptor(NULL, *name, &lookup); 4604 if (!CanInlinePropertyAccess(*map_)) return IsStringLength();
4650 if (lookup.IsFound()) return false; 4605 if (IsArrayLength()) return true;
4651 if (!lookup.IsCacheable()) return false; 4606 if (!LookupDescriptor()) return false;
4652 current = JSObject::cast(current)->GetPrototype(); 4607 if (lookup_.IsFound()) return true;
4608 return LookupInPrototypes();
4609 }
4610
4611
4612 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic(
4613 SmallMapList* types) {
4614 ASSERT(map_.is_identical_to(types->first()));
4615 if (!CanLoadMonomorphic()) return false;
4616 if (types->length() > kMaxLoadPolymorphism) return false;
4617
4618 if (IsStringLength()) {
4619 for (int i = 1; i < types->length(); ++i) {
4620 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
4621 }
4622 return true;
4653 } 4623 }
4624
4625 if (IsArrayLength()) {
4626 bool is_fast = IsFastElementsKind(map_->elements_kind());
4627 for (int i = 1; i < types->length(); ++i) {
4628 Handle<Map> test_map = types->at(i);
4629 if (test_map->instance_type() != JS_ARRAY_TYPE) return false;
4630 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) {
4631 return false;
4632 }
4633 }
4634 return true;
4635 }
4636
4637 if (IsTypedArrayLength()) {
4638 for (int i = 1; i < types->length(); ++i) {
4639 if (types->at(i)->instance_type() != JS_TYPED_ARRAY_TYPE) return false;
4640 }
4641 return true;
4642 }
4643
4644 for (int i = 1; i < types->length(); ++i) {
4645 PropertyAccessInfo test_info(isolate(), types->at(i), name_);
4646 if (!test_info.IsCompatibleForLoad(this)) return false;
4647 }
4648
4654 return true; 4649 return true;
4655 } 4650 }
4656 4651
4657 4652
4653 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic(
4654 PropertyAccessInfo* info,
4655 HValue* object,
4656 HInstruction* checked_object,
4657 BailoutId ast_id,
4658 BailoutId return_id,
4659 bool can_inline_accessor) {
4660 if (info->IsStringLength()) {
4661 return New<HLoadNamedField>(
4662 checked_object, HObjectAccess::ForStringLength());
4663 }
4664
4665 if (info->IsArrayLength()) {
4666 return New<HLoadNamedField>(
4667 checked_object, HObjectAccess::ForArrayLength(
4668 info->map()->elements_kind()));
4669 }
4670
4671 if (info->IsTypedArrayLength()) {
4672 return New<HLoadNamedField>(
4673 checked_object, HObjectAccess::ForTypedArrayLength());
4674 }
4675
4676 HValue* checked_holder = checked_object;
4677 if (info->has_holder()) {
4678 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
4679 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
4680 }
4681
4682 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined();
4683
4684 if (info->lookup()->IsField()) {
4685 return BuildLoadNamedField(checked_holder, info->access());
4686 }
4687
4688 if (info->lookup()->IsPropertyCallbacks()) {
4689 Push(checked_object);
4690 if (FLAG_inline_accessors &&
4691 can_inline_accessor &&
4692 TryInlineGetter(info->accessor(), ast_id, return_id)) {
4693 return NULL;
4694 }
4695 Add<HPushArgument>(Pop());
4696 return new(zone()) HCallConstantFunction(info->accessor(), 1);
4697 }
4698
4699 ASSERT(info->lookup()->IsConstant());
4700 return New<HConstant>(info->constant());
4701 }
4702
4703
4658 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( 4704 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(
4659 int position, 4705 int position,
4660 BailoutId ast_id, 4706 BailoutId ast_id,
4707 BailoutId return_id,
4661 HValue* object, 4708 HValue* object,
4662 SmallMapList* types, 4709 SmallMapList* types,
4663 Handle<String> name) { 4710 Handle<String> name) {
4664 HInstruction* instr = TryLoadPolymorphicAsMonomorphic(object, types, name);
4665 if (instr != NULL) {
4666 instr->set_position(position);
4667 return ast_context()->ReturnInstruction(instr, ast_id);
4668 }
4669
4670 // Something did not match; must use a polymorphic load. 4711 // Something did not match; must use a polymorphic load.
4671 int count = 0; 4712 int count = 0;
4672 HBasicBlock* join = NULL; 4713 HBasicBlock* join = NULL;
4673 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { 4714 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
4674 Handle<Map> map = types->at(i); 4715 PropertyAccessInfo info(isolate(), types->at(i), name);
4675 LookupResult lookup(isolate()); 4716 if (info.CanLoadMonomorphic()) {
4676 if (ComputeLoadStoreField(map, name, &lookup, false) ||
4677 (lookup.IsCacheable() &&
4678 CanInlinePropertyAccess(*map) &&
4679 (lookup.IsConstant() ||
4680 (!lookup.IsFound() &&
4681 PrototypeChainCanNeverResolve(map, name))))) {
4682 if (count == 0) { 4717 if (count == 0) {
4683 BuildCheckHeapObject(object); 4718 BuildCheckHeapObject(object);
4684 join = graph()->CreateBasicBlock(); 4719 join = graph()->CreateBasicBlock();
4685 } 4720 }
4686 ++count; 4721 ++count;
4687 HBasicBlock* if_true = graph()->CreateBasicBlock(); 4722 HBasicBlock* if_true = graph()->CreateBasicBlock();
4688 HBasicBlock* if_false = graph()->CreateBasicBlock(); 4723 HBasicBlock* if_false = graph()->CreateBasicBlock();
4689 HCompareMap* compare = 4724 HCompareMap* compare = New<HCompareMap>(
4690 new(zone()) HCompareMap(object, map, if_true, if_false); 4725 object, info.map(), if_true, if_false);
4691 current_block()->Finish(compare); 4726 current_block()->Finish(compare);
4692 4727
4693 set_current_block(if_true); 4728 set_current_block(if_true);
4694 4729
4695 // TODO(verwaest): Merge logic with BuildLoadNamedMonomorphic. 4730 HInstruction* load = BuildLoadMonomorphic(
4696 if (lookup.IsField()) { 4731 &info, object, compare, ast_id, return_id, FLAG_polymorphic_inlining);
4697 HObjectAccess access = HObjectAccess::ForField(map, &lookup, name); 4732 if (load == NULL) {
4698 HLoadNamedField* load = BuildLoadNamedField(compare, access); 4733 if (HasStackOverflow()) return;
4699 load->set_position(position); 4734 } else {
4700 AddInstruction(load); 4735 if (!load->IsLinked()) {
4736 load->set_position(position);
4737 AddInstruction(load);
4738 }
4701 if (!ast_context()->IsEffect()) Push(load); 4739 if (!ast_context()->IsEffect()) Push(load);
4702 } else if (lookup.IsConstant()) {
4703 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
4704 HConstant* hconstant = Add<HConstant>(constant);
4705 if (!ast_context()->IsEffect()) Push(hconstant);
4706 } else {
4707 ASSERT(!lookup.IsFound());
4708 if (map->prototype()->IsJSObject()) {
4709 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
4710 Handle<JSObject> holder = prototype;
4711 while (holder->map()->prototype()->IsJSObject()) {
4712 holder = handle(JSObject::cast(holder->map()->prototype()));
4713 }
4714 BuildCheckPrototypeMaps(prototype, holder);
4715 }
4716 if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
4717 } 4740 }
4718 4741
4719 current_block()->Goto(join); 4742 if (current_block() != NULL) current_block()->Goto(join);
4720 set_current_block(if_false); 4743 set_current_block(if_false);
4721 } 4744 }
4722 } 4745 }
4723 4746
4724 // Finish up. Unconditionally deoptimize if we've handled all the maps we 4747 // Finish up. Unconditionally deoptimize if we've handled all the maps we
4725 // know about and do not want to handle ones we've never seen. Otherwise 4748 // know about and do not want to handle ones we've never seen. Otherwise
4726 // use a generic IC. 4749 // use a generic IC.
4727 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 4750 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
4751 // Because the deopt may be the only path in the polymorphic load, make sure
4752 // that the environment stack matches the depth on deopt that it otherwise
4753 // would have had after a successful load.
4754 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0());
4728 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join); 4755 FinishExitWithHardDeoptimization("Unknown map in polymorphic load", join);
4729 } else { 4756 } else {
4730 HValue* context = environment()->context(); 4757 HValue* context = environment()->context();
4731 HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name); 4758 HInstruction* load = new(zone()) HLoadNamedGeneric(context, object, name);
4732 load->set_position(position); 4759 load->set_position(position);
4733 AddInstruction(load); 4760 AddInstruction(load);
4734 if (!ast_context()->IsEffect()) Push(load); 4761 if (!ast_context()->IsEffect()) Push(load);
4735 4762
4736 if (join != NULL) { 4763 if (join != NULL) {
4737 current_block()->Goto(join); 4764 current_block()->Goto(join);
(...skipping 15 matching lines...) Expand all
4753 int position, 4780 int position,
4754 BailoutId assignment_id, 4781 BailoutId assignment_id,
4755 HValue* object, 4782 HValue* object,
4756 HValue* value, 4783 HValue* value,
4757 SmallMapList* types, 4784 SmallMapList* types,
4758 Handle<String> name) { 4785 Handle<String> name) {
4759 // Use monomorphic store if property lookup results in the same field index 4786 // Use monomorphic store if property lookup results in the same field index
4760 // for all maps. Requires special map check on the set of all handled maps. 4787 // for all maps. Requires special map check on the set of all handled maps.
4761 if (types->length() > kMaxStorePolymorphism) return false; 4788 if (types->length() > kMaxStorePolymorphism) return false;
4762 4789
4763 // TODO(verwaest): Merge the checking logic with the code in
4764 // TryLoadPolymorphicAsMonomorphic.
4765 LookupResult lookup(isolate()); 4790 LookupResult lookup(isolate());
4766 int count; 4791 int count;
4767 Representation representation = Representation::None(); 4792 Representation representation = Representation::None();
4768 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. 4793 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
4769 for (count = 0; count < types->length(); ++count) { 4794 for (count = 0; count < types->length(); ++count) {
4770 Handle<Map> map = types->at(count); 4795 Handle<Map> map = types->at(count);
4771 // Pass false to ignore transitions. 4796 // Pass false to ignore transitions.
4772 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; 4797 if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
4773 ASSERT(!map->is_observed()); 4798 ASSERT(!map->is_observed());
4774 4799
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
4832 Handle<Map> map = types->at(i); 4857 Handle<Map> map = types->at(i);
4833 LookupResult lookup(isolate()); 4858 LookupResult lookup(isolate());
4834 if (ComputeLoadStoreField(map, name, &lookup, true)) { 4859 if (ComputeLoadStoreField(map, name, &lookup, true)) {
4835 if (count == 0) { 4860 if (count == 0) {
4836 BuildCheckHeapObject(object); 4861 BuildCheckHeapObject(object);
4837 join = graph()->CreateBasicBlock(); 4862 join = graph()->CreateBasicBlock();
4838 } 4863 }
4839 ++count; 4864 ++count;
4840 HBasicBlock* if_true = graph()->CreateBasicBlock(); 4865 HBasicBlock* if_true = graph()->CreateBasicBlock();
4841 HBasicBlock* if_false = graph()->CreateBasicBlock(); 4866 HBasicBlock* if_false = graph()->CreateBasicBlock();
4842 HCompareMap* compare = 4867 HCompareMap* compare = New<HCompareMap>(object, map, if_true, if_false);
4843 new(zone()) HCompareMap(object, map, if_true, if_false);
4844 current_block()->Finish(compare); 4868 current_block()->Finish(compare);
4845 4869
4846 set_current_block(if_true); 4870 set_current_block(if_true);
4847 HInstruction* instr; 4871 HInstruction* instr;
4848 CHECK_ALIVE(instr = BuildStoreNamedField( 4872 CHECK_ALIVE(instr = BuildStoreNamedField(
4849 compare, name, value, map, &lookup)); 4873 compare, name, value, map, &lookup));
4850 instr->set_position(position); 4874 instr->set_position(position);
4851 // Goto will add the HSimulate for the store. 4875 // Goto will add the HSimulate for the store.
4852 AddInstruction(instr); 4876 AddInstruction(instr);
4853 if (!ast_context()->IsEffect()) Push(value); 4877 if (!ast_context()->IsEffect()) Push(value);
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
5353 HValue* object, 5377 HValue* object,
5354 Handle<Map> map, 5378 Handle<Map> map,
5355 Handle<JSFunction> getter, 5379 Handle<JSFunction> getter,
5356 Handle<JSObject> holder) { 5380 Handle<JSObject> holder) {
5357 AddCheckConstantFunction(holder, object, map); 5381 AddCheckConstantFunction(holder, object, map);
5358 Add<HPushArgument>(object); 5382 Add<HPushArgument>(object);
5359 return new(zone()) HCallConstantFunction(getter, 1); 5383 return new(zone()) HCallConstantFunction(getter, 1);
5360 } 5384 }
5361 5385
5362 5386
5363 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic(
5364 HValue* object,
5365 Handle<String> name,
5366 Handle<Map> map) {
5367 // Handle a load from a known field.
5368 ASSERT(!map->is_dictionary_map());
5369
5370 // Handle access to various length properties
5371 if (name->Equals(isolate()->heap()->length_string())) {
5372 if (map->instance_type() == JS_ARRAY_TYPE) {
5373 HCheckMaps* checked_object = AddCheckMap(object, map);
5374 return New<HLoadNamedField>(
5375 checked_object, HObjectAccess::ForArrayLength(map->elements_kind()));
5376 }
5377 }
5378
5379 LookupResult lookup(isolate());
5380 map->LookupDescriptor(NULL, *name, &lookup);
5381 if (lookup.IsField()) {
5382 HCheckMaps* checked_object = AddCheckMap(object, map);
5383 ASSERT(map->IsJSObjectMap());
5384 return BuildLoadNamedField(
5385 checked_object, HObjectAccess::ForField(map, &lookup, name));
5386 }
5387
5388 // Handle a load of a constant known function.
5389 if (lookup.IsConstant()) {
5390 AddCheckMap(object, map);
5391 Handle<Object> constant(lookup.GetConstantFromMap(*map), isolate());
5392 return New<HConstant>(constant);
5393 }
5394
5395 if (lookup.IsFound()) {
5396 // Cannot handle the property, do a generic load instead.
5397 HValue* context = environment()->context();
5398 return new(zone()) HLoadNamedGeneric(context, object, name);
5399 }
5400
5401 // Handle a load from a known field somewhere in the prototype chain.
5402 LookupInPrototypes(map, name, &lookup);
5403 if (lookup.IsField()) {
5404 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5405 Handle<JSObject> holder(lookup.holder());
5406 Handle<Map> holder_map(holder->map());
5407 AddCheckMap(object, map);
5408 HValue* checked_holder = BuildCheckPrototypeMaps(prototype, holder);
5409 return BuildLoadNamedField(
5410 checked_holder, HObjectAccess::ForField(holder_map, &lookup, name));
5411 }
5412
5413 // Handle a load of a constant function somewhere in the prototype chain.
5414 if (lookup.IsConstant()) {
5415 Handle<JSObject> prototype(JSObject::cast(map->prototype()));
5416 Handle<JSObject> holder(lookup.holder());
5417 Handle<Map> holder_map(holder->map());
5418 AddCheckMap(object, map);
5419 BuildCheckPrototypeMaps(prototype, holder);
5420 Handle<Object> constant(lookup.GetConstantFromMap(*holder_map), isolate());
5421 return New<HConstant>(constant);
5422 }
5423
5424 // No luck, do a generic load.
5425 HValue* context = environment()->context();
5426 return new(zone()) HLoadNamedGeneric(context, object, name);
5427 }
5428
5429
5430 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 5387 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object,
5431 HValue* key) { 5388 HValue* key) {
5432 HValue* context = environment()->context(); 5389 HValue* context = environment()->context();
5433 return new(zone()) HLoadKeyedGeneric(context, object, key); 5390 return new(zone()) HLoadKeyedGeneric(context, object, key);
5434 } 5391 }
5435 5392
5436 5393
5437 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { 5394 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
5438 // Loads from a "stock" fast holey double arrays can elide the hole check. 5395 // Loads from a "stock" fast holey double arrays can elide the hole check.
5439 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; 5396 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
5622 5579
5623 HBasicBlock* join = graph()->CreateBasicBlock(); 5580 HBasicBlock* join = graph()->CreateBasicBlock();
5624 5581
5625 for (int i = 0; i < untransitionable_maps.length(); ++i) { 5582 for (int i = 0; i < untransitionable_maps.length(); ++i) {
5626 Handle<Map> map = untransitionable_maps[i]; 5583 Handle<Map> map = untransitionable_maps[i];
5627 if (!map->IsJSObjectMap()) continue; 5584 if (!map->IsJSObjectMap()) continue;
5628 ElementsKind elements_kind = map->elements_kind(); 5585 ElementsKind elements_kind = map->elements_kind();
5629 HBasicBlock* this_map = graph()->CreateBasicBlock(); 5586 HBasicBlock* this_map = graph()->CreateBasicBlock();
5630 HBasicBlock* other_map = graph()->CreateBasicBlock(); 5587 HBasicBlock* other_map = graph()->CreateBasicBlock();
5631 HCompareMap* mapcompare = 5588 HCompareMap* mapcompare =
5632 new(zone()) HCompareMap(object, map, this_map, other_map); 5589 New<HCompareMap>(object, map, this_map, other_map);
5633 current_block()->Finish(mapcompare); 5590 current_block()->Finish(mapcompare);
5634 5591
5635 set_current_block(this_map); 5592 set_current_block(this_map);
5636 HInstruction* access = NULL; 5593 HInstruction* access = NULL;
5637 if (IsDictionaryElementsKind(elements_kind)) { 5594 if (IsDictionaryElementsKind(elements_kind)) {
5638 access = is_store 5595 access = is_store
5639 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val)) 5596 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val))
5640 : AddInstruction(BuildLoadKeyedGeneric(object, key)); 5597 : AddInstruction(BuildLoadKeyedGeneric(object, key));
5641 } else { 5598 } else {
5642 ASSERT(IsFastElementsKind(elements_kind) || 5599 ASSERT(IsFastElementsKind(elements_kind) ||
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
5819 HValue* key, 5776 HValue* key,
5820 int position) { 5777 int position) {
5821 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); 5778 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
5822 Push(object); 5779 Push(object);
5823 if (key != NULL) Push(key); 5780 if (key != NULL) Push(key);
5824 BuildLoad(expr, position, expr->LoadId()); 5781 BuildLoad(expr, position, expr->LoadId());
5825 } 5782 }
5826 5783
5827 5784
5828 static bool AreStringTypes(SmallMapList* types) { 5785 static bool AreStringTypes(SmallMapList* types) {
5829 if (types == NULL || types->length() == 0) return false;
5830 for (int i = 0; i < types->length(); i++) { 5786 for (int i = 0; i < types->length(); i++) {
5831 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; 5787 if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
5832 } 5788 }
5833 return true; 5789 return true;
5834 } 5790 }
5835 5791
5836 5792
5837 void HOptimizedGraphBuilder::BuildLoad(Property* expr, 5793 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
5838 int position, 5794 int position,
5839 BailoutId ast_id) { 5795 BailoutId ast_id) {
5840 HInstruction* instr = NULL; 5796 HInstruction* instr = NULL;
5841 if (expr->IsStringAccess()) { 5797 if (expr->IsStringAccess()) {
5842 HValue* index = Pop(); 5798 HValue* index = Pop();
5843 HValue* string = Pop(); 5799 HValue* string = Pop();
5844 HValue* context = environment()->context(); 5800 HValue* context = environment()->context();
5845 HInstruction* char_code = 5801 HInstruction* char_code =
5846 BuildStringCharCodeAt(string, index); 5802 BuildStringCharCodeAt(string, index);
5847 AddInstruction(char_code); 5803 AddInstruction(char_code);
5848 instr = HStringCharFromCode::New(zone(), context, char_code); 5804 instr = HStringCharFromCode::New(zone(), context, char_code);
5849 5805
5850 } else if (expr->IsFunctionPrototype()) { 5806 } else if (expr->IsFunctionPrototype()) {
5851 HValue* function = Pop(); 5807 HValue* function = Pop();
5852 BuildCheckHeapObject(function); 5808 BuildCheckHeapObject(function);
5853 instr = new(zone()) HLoadFunctionPrototype(function); 5809 instr = new(zone()) HLoadFunctionPrototype(function);
5854 5810
5855 } else if (expr->key()->IsPropertyName()) { 5811 } else if (expr->key()->IsPropertyName()) {
5856 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 5812 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
5857 HValue* object = Top(); 5813 HValue* object = Pop();
5858 5814
5859 SmallMapList* types; 5815 SmallMapList* types;
5860 bool monomorphic = ComputeReceiverTypes(expr, object, &types); 5816 ComputeReceiverTypes(expr, object, &types);
5817 ASSERT(types != NULL);
5861 5818
5862 if (monomorphic) { 5819 if (types->length() > 0) {
5863 Handle<Map> map = types->first(); 5820 PropertyAccessInfo info(isolate(), types->first(), name);
5864 Handle<JSFunction> getter; 5821 if (!info.CanLoadAsMonomorphic(types)) {
5865 Handle<JSObject> holder; 5822 return HandlePolymorphicLoadNamedField(
5866 if (LookupGetter(map, name, &getter, &holder)) { 5823 position, ast_id, expr->LoadId(), object, types, name);
5867 AddCheckConstantFunction(holder, Top(), map); 5824 }
5868 if (FLAG_inline_accessors && 5825
5869 TryInlineGetter(getter, ast_id, expr->LoadId())) { 5826 BuildCheckHeapObject(object);
5870 return; 5827 HInstruction* checked_object;
5871 } 5828 if (AreStringTypes(types)) {
5872 Add<HPushArgument>(Pop()); 5829 checked_object =
5873 instr = new(zone()) HCallConstantFunction(getter, 1); 5830 AddInstruction(HCheckInstanceType::NewIsString(object, zone()));
5874 } else { 5831 } else {
5875 instr = BuildLoadNamedMonomorphic(Pop(), name, map); 5832 checked_object = Add<HCheckMaps>(object, types);
5876 } 5833 }
5877 } else if (AreStringTypes(types) && 5834 instr = BuildLoadMonomorphic(
5878 name->Equals(isolate()->heap()->length_string())) { 5835 &info, object, checked_object, ast_id, expr->LoadId());
5879 BuildCheckHeapObject(Pop()); 5836 if (instr == NULL) return;
5880 HValue* checked_object = 5837 if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
5881 AddInstruction(HCheckInstanceType::NewIsString(object, zone()));
5882 instr = BuildLoadStringLength(object, checked_object);
5883 } else if (types != NULL && types->length() > 1) {
5884 return HandlePolymorphicLoadNamedField(
5885 position, ast_id, Pop(), types, name);
5886 } else { 5838 } else {
5887 instr = BuildLoadNamedGeneric(Pop(), name, expr); 5839 instr = BuildLoadNamedGeneric(object, name, expr);
5888 } 5840 }
5889 5841
5890 } else { 5842 } else {
5891 HValue* key = Pop(); 5843 HValue* key = Pop();
5892 HValue* obj = Pop(); 5844 HValue* obj = Pop();
5893 5845
5894 bool has_side_effects = false; 5846 bool has_side_effects = false;
5895 HValue* load = HandleKeyedElementAccess( 5847 HValue* load = HandleKeyedElementAccess(
5896 obj, key, NULL, expr, ast_id, position, 5848 obj, key, NULL, expr, ast_id, position,
5897 false, // is_store 5849 false, // is_store
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
6012 } 5964 }
6013 5965
6014 5966
6015 bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic( 5967 bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic(
6016 Call* expr, 5968 Call* expr,
6017 HValue* receiver, 5969 HValue* receiver,
6018 SmallMapList* types, 5970 SmallMapList* types,
6019 Handle<String> name) { 5971 Handle<String> name) {
6020 if (types->length() > kMaxCallPolymorphism) return false; 5972 if (types->length() > kMaxCallPolymorphism) return false;
6021 5973
6022 Handle<Map> map(types->at(0)); 5974 PropertyAccessInfo info(isolate(), types->at(0), name);
6023 LookupResult lookup(isolate()); 5975 if (!info.CanLoadAsMonomorphic(types)) return false;
6024 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return false; 5976 if (!expr->ComputeTarget(info.map(), name)) return false;
6025
6026 Handle<Object> prototype(map->prototype(), isolate());
6027 for (int count = 1; count < types->length(); ++count) {
6028 Handle<Map> test_map(types->at(count));
6029 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return false;
6030 if (test_map->prototype() != *prototype) return false;
6031 }
6032
6033 if (!expr->ComputeTarget(map, name)) return false;
6034 5977
6035 BuildCheckHeapObject(receiver); 5978 BuildCheckHeapObject(receiver);
6036 Add<HCheckMaps>(receiver, types); 5979 Add<HCheckMaps>(receiver, types);
6037 AddCheckPrototypeMaps(expr->holder(), map); 5980 AddCheckPrototypeMaps(expr->holder(), info.map());
6038 if (FLAG_trace_inlining) { 5981 if (FLAG_trace_inlining) {
6039 Handle<JSFunction> caller = current_info()->closure(); 5982 Handle<JSFunction> caller = current_info()->closure();
6040 SmartArrayPointer<char> caller_name = 5983 SmartArrayPointer<char> caller_name =
6041 caller->shared()->DebugName()->ToCString(); 5984 caller->shared()->DebugName()->ToCString();
6042 PrintF("Trying to inline the polymorphic call to %s from %s\n", 5985 PrintF("Trying to inline the polymorphic call to %s from %s\n",
6043 *name->ToCString(), *caller_name); 5986 *name->ToCString(), *caller_name);
6044 } 5987 }
6045 5988
6046 if (!TryInlineCall(expr)) { 5989 if (!TryInlineCall(expr)) {
6047 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 5990 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
6104 for (int fn = 0; fn < ordered_functions; ++fn) { 6047 for (int fn = 0; fn < ordered_functions; ++fn) {
6105 int i = order[fn].index(); 6048 int i = order[fn].index();
6106 Handle<Map> map = types->at(i); 6049 Handle<Map> map = types->at(i);
6107 if (fn == 0) { 6050 if (fn == 0) {
6108 // Only needed once. 6051 // Only needed once.
6109 join = graph()->CreateBasicBlock(); 6052 join = graph()->CreateBasicBlock();
6110 if (handle_smi) { 6053 if (handle_smi) {
6111 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); 6054 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
6112 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); 6055 HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
6113 number_block = graph()->CreateBasicBlock(); 6056 number_block = graph()->CreateBasicBlock();
6114 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(receiver); 6057 current_block()->Finish(New<HIsSmiAndBranch>(
6115 smicheck->SetSuccessorAt(0, empty_smi_block); 6058 receiver, empty_smi_block, not_smi_block));
6116 smicheck->SetSuccessorAt(1, not_smi_block);
6117 current_block()->Finish(smicheck);
6118 empty_smi_block->Goto(number_block); 6059 empty_smi_block->Goto(number_block);
6119 set_current_block(not_smi_block); 6060 set_current_block(not_smi_block);
6120 } else { 6061 } else {
6121 BuildCheckHeapObject(receiver); 6062 BuildCheckHeapObject(receiver);
6122 } 6063 }
6123 } 6064 }
6124 HBasicBlock* if_true = graph()->CreateBasicBlock(); 6065 HBasicBlock* if_true = graph()->CreateBasicBlock();
6125 HBasicBlock* if_false = graph()->CreateBasicBlock(); 6066 HBasicBlock* if_false = graph()->CreateBasicBlock();
6126 HUnaryControlInstruction* compare; 6067 HUnaryControlInstruction* compare;
6127 6068
6128 if (handle_smi && map.is_identical_to(number_marker_map)) { 6069 if (handle_smi && map.is_identical_to(number_marker_map)) {
6129 compare = new(zone()) HCompareMap( 6070 compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
6130 receiver, heap_number_map, if_true, if_false);
6131 map = initial_number_map; 6071 map = initial_number_map;
6132 expr->set_number_check( 6072 expr->set_number_check(
6133 Handle<JSObject>(JSObject::cast(map->prototype()))); 6073 Handle<JSObject>(JSObject::cast(map->prototype())));
6134 } else if (map.is_identical_to(string_marker_map)) { 6074 } else if (map.is_identical_to(string_marker_map)) {
6135 compare = new(zone()) HIsStringAndBranch(receiver); 6075 compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
6136 compare->SetSuccessorAt(0, if_true);
6137 compare->SetSuccessorAt(1, if_false);
6138 map = initial_string_map; 6076 map = initial_string_map;
6139 expr->set_string_check( 6077 expr->set_string_check(
6140 Handle<JSObject>(JSObject::cast(map->prototype()))); 6078 Handle<JSObject>(JSObject::cast(map->prototype())));
6141 } else { 6079 } else {
6142 compare = new(zone()) HCompareMap(receiver, map, if_true, if_false); 6080 compare = New<HCompareMap>(receiver, map, if_true, if_false);
6143 expr->set_map_check(); 6081 expr->set_map_check();
6144 } 6082 }
6145 6083
6146 current_block()->Finish(compare); 6084 current_block()->Finish(compare);
6147 6085
6148 if (expr->check_type() == NUMBER_CHECK) { 6086 if (expr->check_type() == NUMBER_CHECK) {
6149 if_true->Goto(number_block); 6087 if_true->Goto(number_block);
6150 if_true = number_block; 6088 if_true = number_block;
6151 number_block->SetJoinId(expr->id()); 6089 number_block->SetJoinId(expr->id());
6152 } 6090 }
(...skipping 1487 matching lines...) Expand 10 before | Expand all | Expand 10 after
7640 return false; 7578 return false;
7641 } 7579 }
7642 return (sub->right() == sa); 7580 return (sub->right() == sa);
7643 } 7581 }
7644 7582
7645 7583
7646 // Checks if the left and the right are shift instructions with the oposite 7584 // Checks if the left and the right are shift instructions with the oposite
7647 // directions that can be replaced by one rotate right instruction or not. 7585 // directions that can be replaced by one rotate right instruction or not.
7648 // Returns the operand and the shift amount for the rotate instruction in the 7586 // Returns the operand and the shift amount for the rotate instruction in the
7649 // former case. 7587 // former case.
7650 bool HOptimizedGraphBuilder::MatchRotateRight(HValue* left, 7588 bool HGraphBuilder::MatchRotateRight(HValue* left,
7651 HValue* right, 7589 HValue* right,
7652 HValue** operand, 7590 HValue** operand,
7653 HValue** shift_amount) { 7591 HValue** shift_amount) {
7654 HShl* shl; 7592 HShl* shl;
7655 HShr* shr; 7593 HShr* shr;
7656 if (left->IsShl() && right->IsShr()) { 7594 if (left->IsShl() && right->IsShr()) {
7657 shl = HShl::cast(left); 7595 shl = HShl::cast(left);
7658 shr = HShr::cast(right); 7596 shr = HShr::cast(right);
7659 } else if (left->IsShr() && right->IsShl()) { 7597 } else if (left->IsShr() && right->IsShl()) {
7660 shl = HShl::cast(right); 7598 shl = HShl::cast(right);
7661 shr = HShr::cast(left); 7599 shr = HShr::cast(left);
7662 } else { 7600 } else {
7663 return false; 7601 return false;
(...skipping 15 matching lines...) Expand all
7679 HConstant* right_const = HConstant::cast(right); 7617 HConstant* right_const = HConstant::cast(right);
7680 if (right_const->HasInteger32Value() && 7618 if (right_const->HasInteger32Value() &&
7681 (right_const->Integer32Value() & 0x1f) != 0) { 7619 (right_const->Integer32Value() & 0x1f) != 0) {
7682 return false; 7620 return false;
7683 } 7621 }
7684 } 7622 }
7685 return true; 7623 return true;
7686 } 7624 }
7687 7625
7688 7626
7627 HValue* HGraphBuilder::EnforceNumberType(HValue* number,
7628 Handle<Type> expected) {
7629 if (expected->Is(Type::Smi())) {
7630 return Add<HForceRepresentation>(number, Representation::Smi());
7631 }
7632 if (expected->Is(Type::Signed32())) {
7633 return Add<HForceRepresentation>(number, Representation::Integer32());
7634 }
7635 return number;
7636 }
7637
7638
7689 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { 7639 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) {
7690 if (value->IsConstant()) { 7640 if (value->IsConstant()) {
7691 HConstant* constant = HConstant::cast(value); 7641 HConstant* constant = HConstant::cast(value);
7692 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); 7642 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone());
7693 if (number.has_value) { 7643 if (number.has_value) {
7694 *expected = handle(Type::Number(), isolate()); 7644 *expected = handle(Type::Number(), isolate());
7695 return AddInstruction(number.value); 7645 return AddInstruction(number.value);
7696 } 7646 }
7697 } 7647 }
7698 7648
7649 Handle<Type> expected_type = *expected;
7650
7651 // Separate the number type from the rest.
7652 Handle<Type> expected_obj = handle(Type::Intersect(
7653 expected_type, handle(Type::NonNumber(), isolate())), isolate());
7654 Handle<Type> expected_number = handle(Type::Intersect(
7655 expected_type, handle(Type::Number(), isolate())), isolate());
7656
7657 // We expect to get a number.
7658 // (We need to check first, since Type::None->Is(Type::Any()) == true.
7659 if (expected_obj->Is(Type::None())) {
7660 ASSERT(!expected_number->Is(Type::None()));
7661 return value;
7662 }
7663
7664 if (expected_obj->Is(Type::Undefined())) {
7665 // This is already done by HChange.
7666 *expected = handle(Type::Union(
7667 expected_number, handle(Type::Double(), isolate())), isolate());
7668 return value;
7669 }
7670
7671 if (expected_obj->Is(Type::Null())) {
7672 *expected = handle(Type::Union(
7673 expected_number, handle(Type::Smi(), isolate())), isolate());
7674 IfBuilder if_null(this);
7675 if_null.If<HCompareObjectEqAndBranch>(value,
7676 graph()->GetConstantNull());
7677 if_null.Then();
7678 Push(graph()->GetConstant0());
7679 if_null.Else();
7680 Push(value);
7681 if_null.End();
7682 return Pop();
7683 }
7684
7685 if (expected_obj->Is(Type::Boolean())) {
7686 *expected = handle(Type::Union(
7687 expected_number, handle(Type::Smi(), isolate())), isolate());
7688 IfBuilder if_true(this);
7689 if_true.If<HCompareObjectEqAndBranch>(value,
7690 graph()->GetConstantTrue());
7691 if_true.Then();
7692 Push(graph()->GetConstant1());
7693 if_true.Else();
7694 IfBuilder if_false(this);
7695 if_false.If<HCompareObjectEqAndBranch>(value,
7696 graph()->GetConstantFalse());
7697 if_false.Then();
7698 Push(graph()->GetConstant0());
7699 if_false.Else();
7700 Push(value);
7701 if_false.End();
7702 if_true.End();
7703 return Pop();
7704 }
7705
7699 return value; 7706 return value;
7700 } 7707 }
7701 7708
7702 7709
7703 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( 7710 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
7704 BinaryOperation* expr, 7711 BinaryOperation* expr,
7705 HValue* left, 7712 HValue* left,
7706 HValue* right) { 7713 HValue* right) {
7707 HValue* context = environment()->context(); 7714 HValue* context = environment()->context();
7708 Handle<Type> left_type = expr->left()->bounds().lower; 7715 Handle<Type> left_type = expr->left()->bounds().lower;
7709 Handle<Type> right_type = expr->right()->bounds().lower; 7716 Handle<Type> right_type = expr->right()->bounds().lower;
7710 Handle<Type> result_type = expr->bounds().lower; 7717 Handle<Type> result_type = expr->bounds().lower;
7711 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); 7718 Maybe<int> fixed_right_arg = expr->fixed_right_arg();
7719
7720 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right,
7721 left_type, right_type, result_type, fixed_right_arg, context);
7722 }
7723
7724
7725 HInstruction* HGraphBuilder::BuildBinaryOperation(
7726 Token::Value op,
7727 HValue* left,
7728 HValue* right,
7729 Handle<Type> left_type,
7730 Handle<Type> right_type,
7731 Handle<Type> result_type,
7732 Maybe<int> fixed_right_arg,
7733 HValue* context) {
7734
7712 Representation left_rep = Representation::FromType(left_type); 7735 Representation left_rep = Representation::FromType(left_type);
7713 Representation right_rep = Representation::FromType(right_type); 7736 Representation right_rep = Representation::FromType(right_type);
7714 Representation result_rep = Representation::FromType(result_type);
7715 7737
7716 if (expr->op() != Token::ADD || 7738 bool maybe_string_add = op == Token::ADD &&
7717 (left->type().IsNonString() && right->type().IsNonString())) { 7739 (left_type->Maybe(Type::String()) ||
7718 // For addition we can only truncate the arguments to number if we can 7740 right_type->Maybe(Type::String()));
7719 // prove that we will not end up in string concatenation mode.
7720 left = TruncateToNumber(left, &left_type);
7721 right = TruncateToNumber(right, &right_type);
7722 }
7723 7741
7724 if (left_type->Is(Type::None())) { 7742 if (left_type->Is(Type::None())) {
7725 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", 7743 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
7726 Deoptimizer::SOFT); 7744 Deoptimizer::SOFT);
7727 // TODO(rossberg): we should be able to get rid of non-continuous defaults. 7745 // TODO(rossberg): we should be able to get rid of non-continuous
7746 // defaults.
7728 left_type = handle(Type::Any(), isolate()); 7747 left_type = handle(Type::Any(), isolate());
7748 } else {
7749 if (!maybe_string_add) left = TruncateToNumber(left, &left_type);
7750 left_rep = Representation::FromType(left_type);
7729 } 7751 }
7752
7730 if (right_type->Is(Type::None())) { 7753 if (right_type->Is(Type::None())) {
7731 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", 7754 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
7732 Deoptimizer::SOFT); 7755 Deoptimizer::SOFT);
7733 right_type = handle(Type::Any(), isolate()); 7756 right_type = handle(Type::Any(), isolate());
7757 } else {
7758 if (!maybe_string_add) right = TruncateToNumber(right, &right_type);
7759 right_rep = Representation::FromType(right_type);
7734 } 7760 }
7761
7762 Representation result_rep = Representation::FromType(result_type);
7763
7764 bool is_string_add = op == Token::ADD &&
7765 (left_type->Is(Type::String()) ||
7766 right_type->Is(Type::String()));
7767
7735 HInstruction* instr = NULL; 7768 HInstruction* instr = NULL;
7736 switch (expr->op()) { 7769 switch (op) {
7737 case Token::ADD: 7770 case Token::ADD:
7738 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { 7771 if (is_string_add) {
7739 BuildCheckHeapObject(left); 7772 StringAddFlags flags = STRING_ADD_CHECK_BOTH;
7740 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); 7773 if (left_type->Is(Type::String())) {
7741 BuildCheckHeapObject(right); 7774 BuildCheckHeapObject(left);
7742 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); 7775 AddInstruction(HCheckInstanceType::NewIsString(left, zone()));
7743 instr = HStringAdd::New(zone(), context, left, right); 7776 flags = STRING_ADD_CHECK_RIGHT;
7777 }
7778 if (right_type->Is(Type::String())) {
7779 BuildCheckHeapObject(right);
7780 AddInstruction(HCheckInstanceType::NewIsString(right, zone()));
7781 flags = (flags == STRING_ADD_CHECK_BOTH)
7782 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE;
7783 }
7784 instr = HStringAdd::New(zone(), context, left, right, flags);
7744 } else { 7785 } else {
7745 instr = HAdd::New(zone(), context, left, right); 7786 instr = HAdd::New(zone(), context, left, right);
7746 } 7787 }
7747 break; 7788 break;
7748 case Token::SUB: 7789 case Token::SUB:
7749 instr = HSub::New(zone(), context, left, right); 7790 instr = HSub::New(zone(), context, left, right);
7750 break; 7791 break;
7751 case Token::MUL: 7792 case Token::MUL:
7752 instr = HMul::New(zone(), context, left, right); 7793 instr = HMul::New(zone(), context, left, right);
7753 break; 7794 break;
7754 case Token::MOD: 7795 case Token::MOD:
7755 instr = HMod::New(zone(), context, left, right, fixed_right_arg); 7796 instr = HMod::New(zone(), context, left, right, fixed_right_arg);
7756 break; 7797 break;
7757 case Token::DIV: 7798 case Token::DIV:
7758 instr = HDiv::New(zone(), context, left, right); 7799 instr = HDiv::New(zone(), context, left, right);
7759 break; 7800 break;
7760 case Token::BIT_XOR: 7801 case Token::BIT_XOR:
7761 case Token::BIT_AND: 7802 case Token::BIT_AND:
7762 instr = NewUncasted<HBitwise>(expr->op(), left, right); 7803 instr = NewUncasted<HBitwise>(op, left, right);
7763 break; 7804 break;
7764 case Token::BIT_OR: { 7805 case Token::BIT_OR: {
7765 HValue* operand, *shift_amount; 7806 HValue* operand, *shift_amount;
7766 if (left_type->Is(Type::Signed32()) && 7807 if (left_type->Is(Type::Signed32()) &&
7767 right_type->Is(Type::Signed32()) && 7808 right_type->Is(Type::Signed32()) &&
7768 MatchRotateRight(left, right, &operand, &shift_amount)) { 7809 MatchRotateRight(left, right, &operand, &shift_amount)) {
7769 instr = new(zone()) HRor(context, operand, shift_amount); 7810 instr = new(zone()) HRor(context, operand, shift_amount);
7770 } else { 7811 } else {
7771 instr = NewUncasted<HBitwise>(expr->op(), left, right); 7812 instr = NewUncasted<HBitwise>(op, left, right);
7772 } 7813 }
7773 break; 7814 break;
7774 } 7815 }
7775 case Token::SAR: 7816 case Token::SAR:
7776 instr = HSar::New(zone(), context, left, right); 7817 instr = HSar::New(zone(), context, left, right);
7777 break; 7818 break;
7778 case Token::SHR: 7819 case Token::SHR:
7779 instr = HShr::New(zone(), context, left, right); 7820 instr = HShr::New(zone(), context, left, right);
7780 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && 7821 if (FLAG_opt_safe_uint32_operations && instr->IsShr() &&
7781 CanBeZero(right)) { 7822 CanBeZero(right)) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
7876 CHECK_ALIVE(VisitForValue(expr->right())); 7917 CHECK_ALIVE(VisitForValue(expr->right()));
7877 } 7918 }
7878 return ast_context()->ReturnValue(Pop()); 7919 return ast_context()->ReturnValue(Pop());
7879 } 7920 }
7880 7921
7881 // We need an extra block to maintain edge-split form. 7922 // We need an extra block to maintain edge-split form.
7882 HBasicBlock* empty_block = graph()->CreateBasicBlock(); 7923 HBasicBlock* empty_block = graph()->CreateBasicBlock();
7883 HBasicBlock* eval_right = graph()->CreateBasicBlock(); 7924 HBasicBlock* eval_right = graph()->CreateBasicBlock();
7884 ToBooleanStub::Types expected(expr->left()->to_boolean_types()); 7925 ToBooleanStub::Types expected(expr->left()->to_boolean_types());
7885 HBranch* test = is_logical_and 7926 HBranch* test = is_logical_and
7886 ? new(zone()) HBranch(left_value, expected, eval_right, empty_block) 7927 ? New<HBranch>(left_value, expected, eval_right, empty_block)
7887 : new(zone()) HBranch(left_value, expected, empty_block, eval_right); 7928 : New<HBranch>(left_value, expected, empty_block, eval_right);
7888 current_block()->Finish(test); 7929 current_block()->Finish(test);
7889 7930
7890 set_current_block(eval_right); 7931 set_current_block(eval_right);
7891 Drop(1); // Value of the left subexpression. 7932 Drop(1); // Value of the left subexpression.
7892 CHECK_BAILOUT(VisitForValue(expr->right())); 7933 CHECK_BAILOUT(VisitForValue(expr->right()));
7893 7934
7894 HBasicBlock* join_block = 7935 HBasicBlock* join_block =
7895 CreateJoin(empty_block, current_block(), expr->id()); 7936 CreateJoin(empty_block, current_block(), expr->id());
7896 set_current_block(join_block); 7937 set_current_block(join_block);
7897 return ast_context()->ReturnValue(Pop()); 7938 return ast_context()->ReturnValue(Pop());
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
8100 HCompareObjectEqAndBranch* result = 8141 HCompareObjectEqAndBranch* result =
8101 New<HCompareObjectEqAndBranch>(left, right); 8142 New<HCompareObjectEqAndBranch>(left, right);
8102 result->set_position(expr->position()); 8143 result->set_position(expr->position());
8103 return ast_context()->ReturnControl(result, expr->id()); 8144 return ast_context()->ReturnControl(result, expr->id());
8104 } else { 8145 } else {
8105 BuildCheckHeapObject(left); 8146 BuildCheckHeapObject(left);
8106 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); 8147 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone()));
8107 BuildCheckHeapObject(right); 8148 BuildCheckHeapObject(right);
8108 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); 8149 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone()));
8109 HCompareObjectEqAndBranch* result = 8150 HCompareObjectEqAndBranch* result =
8110 new(zone()) HCompareObjectEqAndBranch(left, right); 8151 New<HCompareObjectEqAndBranch>(left, right);
8111 result->set_position(expr->position()); 8152 result->set_position(expr->position());
8112 return ast_context()->ReturnControl(result, expr->id()); 8153 return ast_context()->ReturnControl(result, expr->id());
8113 } 8154 }
8114 } 8155 }
8115 default: 8156 default:
8116 return Bailout(kUnsupportedNonPrimitiveCompare); 8157 return Bailout(kUnsupportedNonPrimitiveCompare);
8117 } 8158 }
8118 } else if (combined_type->Is(Type::InternalizedString()) && 8159 } else if (combined_type->Is(Type::InternalizedString()) &&
8119 Token::IsEqualityOp(op)) { 8160 Token::IsEqualityOp(op)) {
8120 BuildCheckHeapObject(left); 8161 BuildCheckHeapObject(left);
8121 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); 8162 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone()));
8122 BuildCheckHeapObject(right); 8163 BuildCheckHeapObject(right);
8123 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); 8164 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone()));
8124 HCompareObjectEqAndBranch* result = 8165 HCompareObjectEqAndBranch* result =
8125 new(zone()) HCompareObjectEqAndBranch(left, right); 8166 New<HCompareObjectEqAndBranch>(left, right);
8126 result->set_position(expr->position()); 8167 result->set_position(expr->position());
8127 return ast_context()->ReturnControl(result, expr->id()); 8168 return ast_context()->ReturnControl(result, expr->id());
8128 } else { 8169 } else {
8129 if (combined_rep.IsTagged() || combined_rep.IsNone()) { 8170 if (combined_rep.IsTagged() || combined_rep.IsNone()) {
8130 HCompareGeneric* result = 8171 HCompareGeneric* result =
8131 new(zone()) HCompareGeneric(context, left, right, op); 8172 new(zone()) HCompareGeneric(context, left, right, op);
8132 result->set_observed_input_representation(1, left_rep); 8173 result->set_observed_input_representation(1, left_rep);
8133 result->set_observed_input_representation(2, right_rep); 8174 result->set_observed_input_representation(2, right_rep);
8134 result->set_position(expr->position()); 8175 result->set_position(expr->position());
8135 return ast_context()->ReturnInstruction(result, expr->id()); 8176 return ast_context()->ReturnInstruction(result, expr->id());
8136 } else { 8177 } else {
8137 HCompareNumericAndBranch* result = 8178 HCompareNumericAndBranch* result =
8138 new(zone()) HCompareNumericAndBranch(left, right, op); 8179 New<HCompareNumericAndBranch>(left, right, op);
8139 result->set_observed_input_representation(left_rep, right_rep); 8180 result->set_observed_input_representation(left_rep, right_rep);
8140 result->set_position(expr->position()); 8181 result->set_position(expr->position());
8141 return ast_context()->ReturnControl(result, expr->id()); 8182 return ast_context()->ReturnControl(result, expr->id());
8142 } 8183 }
8143 } 8184 }
8144 } 8185 }
8145 8186
8146 8187
8147 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 8188 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
8148 Expression* sub_expr, 8189 Expression* sub_expr,
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
8188 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( 8229 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
8189 Handle<JSObject> boilerplate_object, 8230 Handle<JSObject> boilerplate_object,
8190 Handle<Object> allocation_site_object, 8231 Handle<Object> allocation_site_object,
8191 AllocationSiteMode mode) { 8232 AllocationSiteMode mode) {
8192 NoObservableSideEffectsScope no_effects(this); 8233 NoObservableSideEffectsScope no_effects(this);
8193 8234
8194 Handle<FixedArrayBase> elements(boilerplate_object->elements()); 8235 Handle<FixedArrayBase> elements(boilerplate_object->elements());
8195 int object_size = boilerplate_object->map()->instance_size(); 8236 int object_size = boilerplate_object->map()->instance_size();
8196 int object_offset = object_size; 8237 int object_offset = object_size;
8197 8238
8239 InstanceType instance_type = boilerplate_object->map()->instance_type();
8198 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && 8240 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE &&
8199 AllocationSite::CanTrack(boilerplate_object->map()->instance_type()); 8241 AllocationSite::CanTrack(instance_type);
8200 8242
8201 // If using allocation sites, then the payload on the site should already 8243 // If using allocation sites, then the payload on the site should already
8202 // be filled in as a valid (boilerplate) array. 8244 // be filled in as a valid (boilerplate) array.
8203 ASSERT(!create_allocation_site_info || 8245 ASSERT(!create_allocation_site_info ||
8204 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); 8246 AllocationSite::cast(*allocation_site_object)->IsLiteralSite());
8205 8247
8206 if (create_allocation_site_info) { 8248 if (create_allocation_site_info) {
8207 object_size += AllocationMemento::kSize; 8249 object_size += AllocationMemento::kSize;
8208 } 8250 }
8209 8251
8252 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
8253 HType type = instance_type == JS_ARRAY_TYPE
8254 ? HType::JSArray() : HType::JSObject();
8210 HValue* object_size_constant = Add<HConstant>(object_size); 8255 HValue* object_size_constant = Add<HConstant>(object_size);
8211 HInstruction* object = Add<HAllocate>(object_size_constant, HType::JSObject(), 8256 HInstruction* object = Add<HAllocate>(object_size_constant, type,
8212 isolate()->heap()->GetPretenureMode(), JS_OBJECT_TYPE); 8257 isolate()->heap()->GetPretenureMode(), instance_type);
8213 8258
8214 8259
8215 BuildEmitObjectHeader(boilerplate_object, object); 8260 BuildEmitObjectHeader(boilerplate_object, object);
8216 8261
8217 if (create_allocation_site_info) { 8262 if (create_allocation_site_info) {
8218 HInstruction* allocation_site = Add<HConstant>(allocation_site_object); 8263 HInstruction* allocation_site = Add<HConstant>(allocation_site_object);
8219 BuildCreateAllocationMemento(object, object_offset, allocation_site); 8264 BuildCreateAllocationMemento(object, object_offset, allocation_site);
8220 } 8265 }
8221 8266
8222 int elements_size = (elements->length() > 0 && 8267 int elements_size = (elements->length() > 0 &&
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
8566 UNREACHABLE(); 8611 UNREACHABLE();
8567 } 8612 }
8568 8613
8569 8614
8570 // Generators for inline runtime functions. 8615 // Generators for inline runtime functions.
8571 // Support for types. 8616 // Support for types.
8572 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) { 8617 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
8573 ASSERT(call->arguments()->length() == 1); 8618 ASSERT(call->arguments()->length() == 1);
8574 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8619 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8575 HValue* value = Pop(); 8620 HValue* value = Pop();
8576 HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); 8621 HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
8577 return ast_context()->ReturnControl(result, call->id()); 8622 return ast_context()->ReturnControl(result, call->id());
8578 } 8623 }
8579 8624
8580 8625
8581 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { 8626 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
8582 ASSERT(call->arguments()->length() == 1); 8627 ASSERT(call->arguments()->length() == 1);
8583 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8628 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8584 HValue* value = Pop(); 8629 HValue* value = Pop();
8585 HHasInstanceTypeAndBranch* result = 8630 HHasInstanceTypeAndBranch* result =
8586 new(zone()) HHasInstanceTypeAndBranch(value, 8631 new(zone()) HHasInstanceTypeAndBranch(value,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
8627 HHasInstanceTypeAndBranch* result = 8672 HHasInstanceTypeAndBranch* result =
8628 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE); 8673 new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE);
8629 return ast_context()->ReturnControl(result, call->id()); 8674 return ast_context()->ReturnControl(result, call->id());
8630 } 8675 }
8631 8676
8632 8677
8633 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) { 8678 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
8634 ASSERT(call->arguments()->length() == 1); 8679 ASSERT(call->arguments()->length() == 1);
8635 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8680 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8636 HValue* value = Pop(); 8681 HValue* value = Pop();
8637 HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); 8682 HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value);
8638 return ast_context()->ReturnControl(result, call->id()); 8683 return ast_context()->ReturnControl(result, call->id());
8639 } 8684 }
8640 8685
8641 8686
8642 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { 8687 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
8643 return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi); 8688 return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi);
8644 } 8689 }
8645 8690
8646 8691
8647 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { 8692 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
8648 ASSERT(call->arguments()->length() == 1); 8693 ASSERT(call->arguments()->length() == 1);
8649 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8694 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8650 HValue* value = Pop(); 8695 HValue* value = Pop();
8651 HIsUndetectableAndBranch* result = 8696 HIsUndetectableAndBranch* result = New<HIsUndetectableAndBranch>(value);
8652 new(zone()) HIsUndetectableAndBranch(value);
8653 return ast_context()->ReturnControl(result, call->id()); 8697 return ast_context()->ReturnControl(result, call->id());
8654 } 8698 }
8655 8699
8656 8700
8657 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 8701 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
8658 CallRuntime* call) { 8702 CallRuntime* call) {
8659 return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf); 8703 return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf);
8660 } 8704 }
8661 8705
8662 8706
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
8764 } 8808 }
8765 8809
8766 8810
8767 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) { 8811 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
8768 ASSERT(call->arguments()->length() == 2); 8812 ASSERT(call->arguments()->length() == 2);
8769 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8813 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8770 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 8814 CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
8771 HValue* value = Pop(); 8815 HValue* value = Pop();
8772 HValue* object = Pop(); 8816 HValue* object = Pop();
8773 // Check if object is a not a smi. 8817 // Check if object is a not a smi.
8774 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object);
8775 HBasicBlock* if_smi = graph()->CreateBasicBlock(); 8818 HBasicBlock* if_smi = graph()->CreateBasicBlock();
8776 HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); 8819 HBasicBlock* if_heap_object = graph()->CreateBasicBlock();
8777 HBasicBlock* join = graph()->CreateBasicBlock(); 8820 HBasicBlock* join = graph()->CreateBasicBlock();
8778 smicheck->SetSuccessorAt(0, if_smi); 8821 current_block()->Finish(New<HIsSmiAndBranch>(object, if_smi, if_heap_object));
8779 smicheck->SetSuccessorAt(1, if_heap_object);
8780 current_block()->Finish(smicheck);
8781 if_smi->Goto(join); 8822 if_smi->Goto(join);
8782 8823
8783 // Check if object is a JSValue. 8824 // Check if object is a JSValue.
8784 set_current_block(if_heap_object); 8825 set_current_block(if_heap_object);
8785 HHasInstanceTypeAndBranch* typecheck = 8826 HHasInstanceTypeAndBranch* typecheck =
8786 new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE); 8827 new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE);
8787 HBasicBlock* if_js_value = graph()->CreateBasicBlock(); 8828 HBasicBlock* if_js_value = graph()->CreateBasicBlock();
8788 HBasicBlock* not_js_value = graph()->CreateBasicBlock(); 8829 HBasicBlock* not_js_value = graph()->CreateBasicBlock();
8789 typecheck->SetSuccessorAt(0, if_js_value); 8830 typecheck->SetSuccessorAt(0, if_js_value);
8790 typecheck->SetSuccessorAt(1, not_js_value); 8831 typecheck->SetSuccessorAt(1, not_js_value);
(...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after
9699 if (ShouldProduceTraceOutput()) { 9740 if (ShouldProduceTraceOutput()) {
9700 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9741 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
9701 } 9742 }
9702 9743
9703 #ifdef DEBUG 9744 #ifdef DEBUG
9704 graph_->Verify(false); // No full verify. 9745 graph_->Verify(false); // No full verify.
9705 #endif 9746 #endif
9706 } 9747 }
9707 9748
9708 } } // namespace v8::internal 9749 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-bce.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698