| OLD | NEW |
| 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 18 matching lines...) Expand all Loading... |
| 29 | 29 |
| 30 #include <algorithm> | 30 #include <algorithm> |
| 31 | 31 |
| 32 #include "v8.h" | 32 #include "v8.h" |
| 33 #include "codegen.h" | 33 #include "codegen.h" |
| 34 #include "full-codegen.h" | 34 #include "full-codegen.h" |
| 35 #include "hashmap.h" | 35 #include "hashmap.h" |
| 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-check-elimination.h" |
| 39 #include "hydrogen-dce.h" | 40 #include "hydrogen-dce.h" |
| 40 #include "hydrogen-dehoist.h" | 41 #include "hydrogen-dehoist.h" |
| 41 #include "hydrogen-deoptimizing-mark.h" | 42 #include "hydrogen-deoptimizing-mark.h" |
| 42 #include "hydrogen-environment-liveness.h" | 43 #include "hydrogen-environment-liveness.h" |
| 43 #include "hydrogen-escape-analysis.h" | 44 #include "hydrogen-escape-analysis.h" |
| 44 #include "hydrogen-infer-representation.h" | 45 #include "hydrogen-infer-representation.h" |
| 45 #include "hydrogen-infer-types.h" | 46 #include "hydrogen-infer-types.h" |
| 46 #include "hydrogen-load-elimination.h" | 47 #include "hydrogen-load-elimination.h" |
| 47 #include "hydrogen-gvn.h" | 48 #include "hydrogen-gvn.h" |
| 48 #include "hydrogen-mark-deoptimize.h" | 49 #include "hydrogen-mark-deoptimize.h" |
| (...skipping 2191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2240 loop_entry->PostProcessLoopHeader(statement); | 2241 loop_entry->PostProcessLoopHeader(statement); |
| 2241 if (break_block != NULL) { | 2242 if (break_block != NULL) { |
| 2242 if (loop_successor != NULL) loop_successor->Goto(break_block); | 2243 if (loop_successor != NULL) loop_successor->Goto(break_block); |
| 2243 break_block->SetJoinId(statement->ExitId()); | 2244 break_block->SetJoinId(statement->ExitId()); |
| 2244 return break_block; | 2245 return break_block; |
| 2245 } | 2246 } |
| 2246 return loop_successor; | 2247 return loop_successor; |
| 2247 } | 2248 } |
| 2248 | 2249 |
| 2249 | 2250 |
| 2251 // Build a new loop header block and set it as the current block. |
| 2252 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() { |
| 2253 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
| 2254 current_block()->Goto(loop_entry); |
| 2255 set_current_block(loop_entry); |
| 2256 return loop_entry; |
| 2257 } |
| 2258 |
| 2259 |
| 2260 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry( |
| 2261 IterationStatement* statement) { |
| 2262 HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement) |
| 2263 ? osr()->BuildOsrLoopEntry(statement) |
| 2264 : BuildLoopEntry(); |
| 2265 return loop_entry; |
| 2266 } |
| 2267 |
| 2268 |
| 2250 void HBasicBlock::FinishExit(HControlInstruction* instruction) { | 2269 void HBasicBlock::FinishExit(HControlInstruction* instruction) { |
| 2251 Finish(instruction); | 2270 Finish(instruction); |
| 2252 ClearEnvironment(); | 2271 ClearEnvironment(); |
| 2253 } | 2272 } |
| 2254 | 2273 |
| 2255 | 2274 |
| 2256 HGraph::HGraph(CompilationInfo* info) | 2275 HGraph::HGraph(CompilationInfo* info) |
| 2257 : isolate_(info->isolate()), | 2276 : isolate_(info->isolate()), |
| 2258 next_block_id_(0), | 2277 next_block_id_(0), |
| 2259 entry_block_(NULL), | 2278 entry_block_(NULL), |
| (...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3056 set_current_block(body_entry); | 3075 set_current_block(body_entry); |
| 3057 | 3076 |
| 3058 // Handle implicit declaration of the function name in named function | 3077 // Handle implicit declaration of the function name in named function |
| 3059 // expressions before other declarations. | 3078 // expressions before other declarations. |
| 3060 if (scope->is_function_scope() && scope->function() != NULL) { | 3079 if (scope->is_function_scope() && scope->function() != NULL) { |
| 3061 VisitVariableDeclaration(scope->function()); | 3080 VisitVariableDeclaration(scope->function()); |
| 3062 } | 3081 } |
| 3063 VisitDeclarations(scope->declarations()); | 3082 VisitDeclarations(scope->declarations()); |
| 3064 Add<HSimulate>(BailoutId::Declarations()); | 3083 Add<HSimulate>(BailoutId::Declarations()); |
| 3065 | 3084 |
| 3066 HValue* context = environment()->context(); | 3085 Add<HStackCheck>(HStackCheck::kFunctionEntry); |
| 3067 Add<HStackCheck>(context, HStackCheck::kFunctionEntry); | |
| 3068 | 3086 |
| 3069 VisitStatements(current_info()->function()->body()); | 3087 VisitStatements(current_info()->function()->body()); |
| 3070 if (HasStackOverflow()) return false; | 3088 if (HasStackOverflow()) return false; |
| 3071 | 3089 |
| 3072 if (current_block() != NULL) { | 3090 if (current_block() != NULL) { |
| 3073 Add<HReturn>(graph()->GetConstantUndefined()); | 3091 Add<HReturn>(graph()->GetConstantUndefined()); |
| 3074 set_current_block(NULL); | 3092 set_current_block(NULL); |
| 3075 } | 3093 } |
| 3076 | 3094 |
| 3077 // If the checksum of the number of type info changes is the same as the | 3095 // If the checksum of the number of type info changes is the same as the |
| 3078 // last time this function was compiled, then this recompile is likely not | 3096 // last time this function was compiled, then this recompile is likely not |
| 3079 // due to missing/inadequate type feedback, but rather too aggressive | 3097 // due to missing/inadequate type feedback, but rather too aggressive |
| 3080 // optimization. Disable optimistic LICM in that case. | 3098 // optimization. Disable optimistic LICM in that case. |
| 3081 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); | 3099 Handle<Code> unoptimized_code(current_info()->shared_info()->code()); |
| 3082 ASSERT(unoptimized_code->kind() == Code::FUNCTION); | 3100 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 3083 Handle<TypeFeedbackInfo> type_info( | 3101 Handle<TypeFeedbackInfo> type_info( |
| 3084 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | 3102 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); |
| 3085 int checksum = type_info->own_type_change_checksum(); | 3103 int checksum = type_info->own_type_change_checksum(); |
| 3086 int composite_checksum = graph()->update_type_change_checksum(checksum); | 3104 int composite_checksum = graph()->update_type_change_checksum(checksum); |
| 3087 graph()->set_use_optimistic_licm( | 3105 graph()->set_use_optimistic_licm( |
| 3088 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | 3106 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
| 3089 type_info->set_inlined_type_change_checksum(composite_checksum); | 3107 type_info->set_inlined_type_change_checksum(composite_checksum); |
| 3090 | 3108 |
| 3091 // Perform any necessary OSR-specific cleanups or changes to the graph. | 3109 // Perform any necessary OSR-specific cleanups or changes to the graph. |
| 3092 osr_->FinishGraph(); | 3110 osr()->FinishGraph(); |
| 3093 | 3111 |
| 3094 return true; | 3112 return true; |
| 3095 } | 3113 } |
| 3096 | 3114 |
| 3097 | 3115 |
| 3098 bool HGraph::Optimize(BailoutReason* bailout_reason) { | 3116 bool HGraph::Optimize(BailoutReason* bailout_reason) { |
| 3099 OrderBlocks(); | 3117 OrderBlocks(); |
| 3100 AssignDominators(); | 3118 AssignDominators(); |
| 3101 | 3119 |
| 3102 // We need to create a HConstant "zero" now so that GVN will fold every | 3120 // We need to create a HConstant "zero" now so that GVN will fold every |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3118 if (!CheckConstPhiUses()) { | 3136 if (!CheckConstPhiUses()) { |
| 3119 *bailout_reason = kUnsupportedPhiUseOfConstVariable; | 3137 *bailout_reason = kUnsupportedPhiUseOfConstVariable; |
| 3120 return false; | 3138 return false; |
| 3121 } | 3139 } |
| 3122 Run<HRedundantPhiEliminationPhase>(); | 3140 Run<HRedundantPhiEliminationPhase>(); |
| 3123 if (!CheckArgumentsPhiUses()) { | 3141 if (!CheckArgumentsPhiUses()) { |
| 3124 *bailout_reason = kUnsupportedPhiUseOfArguments; | 3142 *bailout_reason = kUnsupportedPhiUseOfArguments; |
| 3125 return false; | 3143 return false; |
| 3126 } | 3144 } |
| 3127 | 3145 |
| 3128 // Remove dead code and phis | 3146 if (FLAG_check_elimination) Run<HCheckEliminationPhase>(); |
| 3129 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); | 3147 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
| 3130 | |
| 3131 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); | 3148 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); |
| 3132 | 3149 |
| 3133 if (FLAG_load_elimination) Run<HLoadEliminationPhase>(); | 3150 if (FLAG_load_elimination) Run<HLoadEliminationPhase>(); |
| 3134 | 3151 |
| 3135 CollectPhis(); | 3152 CollectPhis(); |
| 3136 | 3153 |
| 3137 if (has_osr()) osr()->FinishOsrValues(); | 3154 if (has_osr()) osr()->FinishOsrValues(); |
| 3138 | 3155 |
| 3139 Run<HInferRepresentationPhase>(); | 3156 Run<HInferRepresentationPhase>(); |
| 3140 | 3157 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3158 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); | 3175 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); |
| 3159 | 3176 |
| 3160 if (FLAG_use_range) Run<HRangeAnalysisPhase>(); | 3177 if (FLAG_use_range) Run<HRangeAnalysisPhase>(); |
| 3161 | 3178 |
| 3162 Run<HComputeChangeUndefinedToNaN>(); | 3179 Run<HComputeChangeUndefinedToNaN>(); |
| 3163 Run<HComputeMinusZeroChecksPhase>(); | 3180 Run<HComputeMinusZeroChecksPhase>(); |
| 3164 | 3181 |
| 3165 // Eliminate redundant stack checks on backwards branches. | 3182 // Eliminate redundant stack checks on backwards branches. |
| 3166 Run<HStackCheckEliminationPhase>(); | 3183 Run<HStackCheckEliminationPhase>(); |
| 3167 | 3184 |
| 3168 if (FLAG_array_bounds_checks_elimination) { | 3185 if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>(); |
| 3169 Run<HBoundsCheckEliminationPhase>(); | 3186 if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>(); |
| 3170 } | |
| 3171 if (FLAG_array_bounds_checks_hoisting) { | |
| 3172 Run<HBoundsCheckHoistingPhase>(); | |
| 3173 } | |
| 3174 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>(); | 3187 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>(); |
| 3175 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); | 3188 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); |
| 3176 | 3189 |
| 3177 RestoreActualValues(); | 3190 RestoreActualValues(); |
| 3178 | 3191 |
| 3179 return true; | 3192 return true; |
| 3180 } | 3193 } |
| 3181 | 3194 |
| 3182 | 3195 |
| 3183 void HGraph::RestoreActualValues() { | 3196 void HGraph::RestoreActualValues() { |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3513 int clause_count = clauses->length(); | 3526 int clause_count = clauses->length(); |
| 3514 if (clause_count > kCaseClauseLimit) { | 3527 if (clause_count > kCaseClauseLimit) { |
| 3515 return Bailout(kSwitchStatementTooManyClauses); | 3528 return Bailout(kSwitchStatementTooManyClauses); |
| 3516 } | 3529 } |
| 3517 | 3530 |
| 3518 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); | 3531 ASSERT(stmt->switch_type() != SwitchStatement::UNKNOWN_SWITCH); |
| 3519 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { | 3532 if (stmt->switch_type() == SwitchStatement::GENERIC_SWITCH) { |
| 3520 return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels); | 3533 return Bailout(kSwitchStatementMixedOrNonLiteralSwitchLabels); |
| 3521 } | 3534 } |
| 3522 | 3535 |
| 3523 HValue* context = environment()->context(); | |
| 3524 | |
| 3525 CHECK_ALIVE(VisitForValue(stmt->tag())); | 3536 CHECK_ALIVE(VisitForValue(stmt->tag())); |
| 3526 Add<HSimulate>(stmt->EntryId()); | 3537 Add<HSimulate>(stmt->EntryId()); |
| 3527 HValue* tag_value = Pop(); | 3538 HValue* tag_value = Pop(); |
| 3528 HBasicBlock* first_test_block = current_block(); | 3539 HBasicBlock* first_test_block = current_block(); |
| 3529 | 3540 |
| 3530 HUnaryControlInstruction* string_check = NULL; | 3541 HUnaryControlInstruction* string_check = NULL; |
| 3531 HBasicBlock* not_string_block = NULL; | 3542 HBasicBlock* not_string_block = NULL; |
| 3532 | 3543 |
| 3533 // Test switch's tag value if all clauses are string literals | 3544 // Test switch's tag value if all clauses are string literals |
| 3534 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { | 3545 if (stmt->switch_type() == SwitchStatement::STRING_SWITCH) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3565 } | 3576 } |
| 3566 | 3577 |
| 3567 HCompareNumericAndBranch* compare_ = | 3578 HCompareNumericAndBranch* compare_ = |
| 3568 New<HCompareNumericAndBranch>(tag_value, | 3579 New<HCompareNumericAndBranch>(tag_value, |
| 3569 label_value, | 3580 label_value, |
| 3570 Token::EQ_STRICT); | 3581 Token::EQ_STRICT); |
| 3571 compare_->set_observed_input_representation( | 3582 compare_->set_observed_input_representation( |
| 3572 Representation::Smi(), Representation::Smi()); | 3583 Representation::Smi(), Representation::Smi()); |
| 3573 compare = compare_; | 3584 compare = compare_; |
| 3574 } else { | 3585 } else { |
| 3575 compare = new(zone()) HStringCompareAndBranch(context, tag_value, | 3586 compare = New<HStringCompareAndBranch>(tag_value, |
| 3576 label_value, | 3587 label_value, |
| 3577 Token::EQ_STRICT); | 3588 Token::EQ_STRICT); |
| 3578 } | 3589 } |
| 3579 | 3590 |
| 3580 compare->SetSuccessorAt(0, body_block); | 3591 compare->SetSuccessorAt(0, body_block); |
| 3581 compare->SetSuccessorAt(1, next_test_block); | 3592 compare->SetSuccessorAt(1, next_test_block); |
| 3582 current_block()->Finish(compare); | 3593 current_block()->Finish(compare); |
| 3583 | 3594 |
| 3584 set_current_block(next_test_block); | 3595 set_current_block(next_test_block); |
| 3585 } | 3596 } |
| 3586 | 3597 |
| 3587 // Save the current block to use for the default or to join with the | 3598 // Save the current block to use for the default or to join with the |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3659 set_current_block(break_block); | 3670 set_current_block(break_block); |
| 3660 } | 3671 } |
| 3661 } | 3672 } |
| 3662 | 3673 |
| 3663 | 3674 |
| 3664 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, | 3675 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt, |
| 3665 HBasicBlock* loop_entry, | 3676 HBasicBlock* loop_entry, |
| 3666 BreakAndContinueInfo* break_info) { | 3677 BreakAndContinueInfo* break_info) { |
| 3667 BreakAndContinueScope push(break_info, this); | 3678 BreakAndContinueScope push(break_info, this); |
| 3668 Add<HSimulate>(stmt->StackCheckId()); | 3679 Add<HSimulate>(stmt->StackCheckId()); |
| 3669 HValue* context = environment()->context(); | 3680 HStackCheck* stack_check = |
| 3670 HStackCheck* stack_check = HStackCheck::cast(Add<HStackCheck>( | 3681 HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch)); |
| 3671 context, HStackCheck::kBackwardsBranch)); | |
| 3672 ASSERT(loop_entry->IsLoopHeader()); | 3682 ASSERT(loop_entry->IsLoopHeader()); |
| 3673 loop_entry->loop_information()->set_stack_check(stack_check); | 3683 loop_entry->loop_information()->set_stack_check(stack_check); |
| 3674 CHECK_BAILOUT(Visit(stmt->body())); | 3684 CHECK_BAILOUT(Visit(stmt->body())); |
| 3675 } | 3685 } |
| 3676 | 3686 |
| 3677 | 3687 |
| 3678 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 3688 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 3679 ASSERT(!HasStackOverflow()); | 3689 ASSERT(!HasStackOverflow()); |
| 3680 ASSERT(current_block() != NULL); | 3690 ASSERT(current_block() != NULL); |
| 3681 ASSERT(current_block()->HasPredecessor()); | 3691 ASSERT(current_block()->HasPredecessor()); |
| 3682 ASSERT(current_block() != NULL); | 3692 ASSERT(current_block() != NULL); |
| 3683 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt); | 3693 HBasicBlock* loop_entry = BuildLoopEntry(stmt); |
| 3684 | 3694 |
| 3685 BreakAndContinueInfo break_info(stmt); | 3695 BreakAndContinueInfo break_info(stmt); |
| 3686 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); | 3696 CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); |
| 3687 HBasicBlock* body_exit = | 3697 HBasicBlock* body_exit = |
| 3688 JoinContinue(stmt, current_block(), break_info.continue_block()); | 3698 JoinContinue(stmt, current_block(), break_info.continue_block()); |
| 3689 HBasicBlock* loop_successor = NULL; | 3699 HBasicBlock* loop_successor = NULL; |
| 3690 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { | 3700 if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { |
| 3691 set_current_block(body_exit); | 3701 set_current_block(body_exit); |
| 3692 // The block for a true condition, the actual predecessor block of the | 3702 // The block for a true condition, the actual predecessor block of the |
| 3693 // back edge. | 3703 // back edge. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3712 break_info.break_block()); | 3722 break_info.break_block()); |
| 3713 set_current_block(loop_exit); | 3723 set_current_block(loop_exit); |
| 3714 } | 3724 } |
| 3715 | 3725 |
| 3716 | 3726 |
| 3717 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { | 3727 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { |
| 3718 ASSERT(!HasStackOverflow()); | 3728 ASSERT(!HasStackOverflow()); |
| 3719 ASSERT(current_block() != NULL); | 3729 ASSERT(current_block() != NULL); |
| 3720 ASSERT(current_block()->HasPredecessor()); | 3730 ASSERT(current_block()->HasPredecessor()); |
| 3721 ASSERT(current_block() != NULL); | 3731 ASSERT(current_block() != NULL); |
| 3722 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt); | 3732 HBasicBlock* loop_entry = BuildLoopEntry(stmt); |
| 3723 | 3733 |
| 3724 // If the condition is constant true, do not generate a branch. | 3734 // If the condition is constant true, do not generate a branch. |
| 3725 HBasicBlock* loop_successor = NULL; | 3735 HBasicBlock* loop_successor = NULL; |
| 3726 if (!stmt->cond()->ToBooleanIsTrue()) { | 3736 if (!stmt->cond()->ToBooleanIsTrue()) { |
| 3727 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 3737 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
| 3728 loop_successor = graph()->CreateBasicBlock(); | 3738 loop_successor = graph()->CreateBasicBlock(); |
| 3729 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); | 3739 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
| 3730 if (body_entry->HasPredecessor()) { | 3740 if (body_entry->HasPredecessor()) { |
| 3731 body_entry->SetJoinId(stmt->BodyId()); | 3741 body_entry->SetJoinId(stmt->BodyId()); |
| 3732 set_current_block(body_entry); | 3742 set_current_block(body_entry); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3754 | 3764 |
| 3755 | 3765 |
| 3756 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { | 3766 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) { |
| 3757 ASSERT(!HasStackOverflow()); | 3767 ASSERT(!HasStackOverflow()); |
| 3758 ASSERT(current_block() != NULL); | 3768 ASSERT(current_block() != NULL); |
| 3759 ASSERT(current_block()->HasPredecessor()); | 3769 ASSERT(current_block()->HasPredecessor()); |
| 3760 if (stmt->init() != NULL) { | 3770 if (stmt->init() != NULL) { |
| 3761 CHECK_ALIVE(Visit(stmt->init())); | 3771 CHECK_ALIVE(Visit(stmt->init())); |
| 3762 } | 3772 } |
| 3763 ASSERT(current_block() != NULL); | 3773 ASSERT(current_block() != NULL); |
| 3764 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt); | 3774 HBasicBlock* loop_entry = BuildLoopEntry(stmt); |
| 3765 | 3775 |
| 3766 HBasicBlock* loop_successor = NULL; | 3776 HBasicBlock* loop_successor = NULL; |
| 3767 if (stmt->cond() != NULL) { | 3777 if (stmt->cond() != NULL) { |
| 3768 HBasicBlock* body_entry = graph()->CreateBasicBlock(); | 3778 HBasicBlock* body_entry = graph()->CreateBasicBlock(); |
| 3769 loop_successor = graph()->CreateBasicBlock(); | 3779 loop_successor = graph()->CreateBasicBlock(); |
| 3770 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); | 3780 CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); |
| 3771 if (body_entry->HasPredecessor()) { | 3781 if (body_entry->HasPredecessor()) { |
| 3772 body_entry->SetJoinId(stmt->BodyId()); | 3782 body_entry->SetJoinId(stmt->BodyId()); |
| 3773 set_current_block(body_entry); | 3783 set_current_block(body_entry); |
| 3774 } | 3784 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3837 Push(map); | 3847 Push(map); |
| 3838 Push(array); | 3848 Push(array); |
| 3839 Push(enum_length); | 3849 Push(enum_length); |
| 3840 Push(start_index); | 3850 Push(start_index); |
| 3841 | 3851 |
| 3842 HInstruction* index_cache = Add<HForInCacheArray>( | 3852 HInstruction* index_cache = Add<HForInCacheArray>( |
| 3843 enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex); | 3853 enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex); |
| 3844 HForInCacheArray::cast(array)->set_index_cache( | 3854 HForInCacheArray::cast(array)->set_index_cache( |
| 3845 HForInCacheArray::cast(index_cache)); | 3855 HForInCacheArray::cast(index_cache)); |
| 3846 | 3856 |
| 3847 HBasicBlock* loop_entry = osr_->BuildPossibleOsrLoopEntry(stmt); | 3857 HBasicBlock* loop_entry = BuildLoopEntry(stmt); |
| 3848 | 3858 |
| 3849 HValue* index = environment()->ExpressionStackAt(0); | 3859 HValue* index = environment()->ExpressionStackAt(0); |
| 3850 HValue* limit = environment()->ExpressionStackAt(1); | 3860 HValue* limit = environment()->ExpressionStackAt(1); |
| 3851 | 3861 |
| 3852 // Check that we still have more keys. | 3862 // Check that we still have more keys. |
| 3853 HCompareNumericAndBranch* compare_index = | 3863 HCompareNumericAndBranch* compare_index = |
| 3854 New<HCompareNumericAndBranch>(index, limit, Token::LT); | 3864 New<HCompareNumericAndBranch>(index, limit, Token::LT); |
| 3855 compare_index->set_observed_input_representation( | 3865 compare_index->set_observed_input_representation( |
| 3856 Representation::Smi(), Representation::Smi()); | 3866 Representation::Smi(), Representation::Smi()); |
| 3857 | 3867 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3962 ASSERT(!HasStackOverflow()); | 3972 ASSERT(!HasStackOverflow()); |
| 3963 ASSERT(current_block() != NULL); | 3973 ASSERT(current_block() != NULL); |
| 3964 ASSERT(current_block()->HasPredecessor()); | 3974 ASSERT(current_block()->HasPredecessor()); |
| 3965 Handle<SharedFunctionInfo> shared_info = | 3975 Handle<SharedFunctionInfo> shared_info = |
| 3966 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr); | 3976 SearchSharedFunctionInfo(current_info()->shared_info()->code(), expr); |
| 3967 if (shared_info.is_null()) { | 3977 if (shared_info.is_null()) { |
| 3968 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); | 3978 shared_info = Compiler::BuildFunctionInfo(expr, current_info()->script()); |
| 3969 } | 3979 } |
| 3970 // We also have a stack overflow if the recursive compilation did. | 3980 // We also have a stack overflow if the recursive compilation did. |
| 3971 if (HasStackOverflow()) return; | 3981 if (HasStackOverflow()) return; |
| 3972 HValue* context = environment()->context(); | |
| 3973 HFunctionLiteral* instr = | 3982 HFunctionLiteral* instr = |
| 3974 new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); | 3983 New<HFunctionLiteral>(shared_info, expr->pretenure()); |
| 3975 return ast_context()->ReturnInstruction(instr, expr->id()); | 3984 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 3976 } | 3985 } |
| 3977 | 3986 |
| 3978 | 3987 |
| 3979 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( | 3988 void HOptimizedGraphBuilder::VisitSharedFunctionInfoLiteral( |
| 3980 SharedFunctionInfoLiteral* expr) { | 3989 SharedFunctionInfoLiteral* expr) { |
| 3981 ASSERT(!HasStackOverflow()); | 3990 ASSERT(!HasStackOverflow()); |
| 3982 ASSERT(current_block() != NULL); | 3991 ASSERT(current_block() != NULL); |
| 3983 ASSERT(current_block()->HasPredecessor()); | 3992 ASSERT(current_block()->HasPredecessor()); |
| 3984 return Bailout(kSharedFunctionInfoLiteral); | 3993 return Bailout(kSharedFunctionInfoLiteral); |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4143 return ast_context()->ReturnInstruction(instr, expr->id()); | 4152 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4144 } | 4153 } |
| 4145 | 4154 |
| 4146 | 4155 |
| 4147 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 4156 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 4148 ASSERT(!HasStackOverflow()); | 4157 ASSERT(!HasStackOverflow()); |
| 4149 ASSERT(current_block() != NULL); | 4158 ASSERT(current_block() != NULL); |
| 4150 ASSERT(current_block()->HasPredecessor()); | 4159 ASSERT(current_block()->HasPredecessor()); |
| 4151 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4160 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 4152 Handle<FixedArray> literals(closure->literals()); | 4161 Handle<FixedArray> literals(closure->literals()); |
| 4153 HValue* context = environment()->context(); | 4162 HRegExpLiteral* instr = New<HRegExpLiteral>(literals, |
| 4154 | 4163 expr->pattern(), |
| 4155 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, | 4164 expr->flags(), |
| 4156 literals, | 4165 expr->literal_index()); |
| 4157 expr->pattern(), | |
| 4158 expr->flags(), | |
| 4159 expr->literal_index()); | |
| 4160 return ast_context()->ReturnInstruction(instr, expr->id()); | 4166 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 4161 } | 4167 } |
| 4162 | 4168 |
| 4163 | 4169 |
| 4164 static bool CanInlinePropertyAccess(Map* type) { | 4170 static bool CanInlinePropertyAccess(Map* type) { |
| 4165 return type->IsJSObjectMap() && | 4171 return type->IsJSObjectMap() && |
| 4166 !type->is_dictionary_map() && | 4172 !type->is_dictionary_map() && |
| 4167 !type->has_named_interceptor(); | 4173 !type->has_named_interceptor(); |
| 4168 } | 4174 } |
| 4169 | 4175 |
| (...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4761 map->LookupDescriptor(*holder_, *name_, &lookup_); | 4767 map->LookupDescriptor(*holder_, *name_, &lookup_); |
| 4762 if (lookup_.IsFound()) return LoadResult(map); | 4768 if (lookup_.IsFound()) return LoadResult(map); |
| 4763 } | 4769 } |
| 4764 lookup_.NotFound(); | 4770 lookup_.NotFound(); |
| 4765 return true; | 4771 return true; |
| 4766 } | 4772 } |
| 4767 | 4773 |
| 4768 | 4774 |
| 4769 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() { | 4775 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadMonomorphic() { |
| 4770 if (!CanInlinePropertyAccess(*map_)) return IsStringLength(); | 4776 if (!CanInlinePropertyAccess(*map_)) return IsStringLength(); |
| 4771 if (IsArrayLength()) return true; | 4777 if (IsJSObjectFieldAccessor()) return true; |
| 4772 if (!LookupDescriptor()) return false; | 4778 if (!LookupDescriptor()) return false; |
| 4773 if (lookup_.IsFound()) return true; | 4779 if (lookup_.IsFound()) return true; |
| 4774 return LookupInPrototypes(); | 4780 return LookupInPrototypes(); |
| 4775 } | 4781 } |
| 4776 | 4782 |
| 4777 | 4783 |
| 4778 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic( | 4784 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanLoadAsMonomorphic( |
| 4779 SmallMapList* types) { | 4785 SmallMapList* types) { |
| 4780 ASSERT(map_.is_identical_to(types->first())); | 4786 ASSERT(map_.is_identical_to(types->first())); |
| 4781 if (!CanLoadMonomorphic()) return false; | 4787 if (!CanLoadMonomorphic()) return false; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4793 for (int i = 1; i < types->length(); ++i) { | 4799 for (int i = 1; i < types->length(); ++i) { |
| 4794 Handle<Map> test_map = types->at(i); | 4800 Handle<Map> test_map = types->at(i); |
| 4795 if (test_map->instance_type() != JS_ARRAY_TYPE) return false; | 4801 if (test_map->instance_type() != JS_ARRAY_TYPE) return false; |
| 4796 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) { | 4802 if (IsFastElementsKind(test_map->elements_kind()) != is_fast) { |
| 4797 return false; | 4803 return false; |
| 4798 } | 4804 } |
| 4799 } | 4805 } |
| 4800 return true; | 4806 return true; |
| 4801 } | 4807 } |
| 4802 | 4808 |
| 4803 if (IsTypedArrayLength()) { | 4809 if (IsJSObjectFieldAccessor()) { |
| 4810 InstanceType instance_type = map_->instance_type(); |
| 4804 for (int i = 1; i < types->length(); ++i) { | 4811 for (int i = 1; i < types->length(); ++i) { |
| 4805 if (types->at(i)->instance_type() != JS_TYPED_ARRAY_TYPE) return false; | 4812 if (types->at(i)->instance_type() != instance_type) return false; |
| 4806 } | 4813 } |
| 4807 return true; | 4814 return true; |
| 4808 } | 4815 } |
| 4809 | 4816 |
| 4810 for (int i = 1; i < types->length(); ++i) { | 4817 for (int i = 1; i < types->length(); ++i) { |
| 4811 PropertyAccessInfo test_info(isolate(), types->at(i), name_); | 4818 PropertyAccessInfo test_info(isolate(), types->at(i), name_); |
| 4812 if (!test_info.IsCompatibleForLoad(this)) return false; | 4819 if (!test_info.IsCompatibleForLoad(this)) return false; |
| 4813 } | 4820 } |
| 4814 | 4821 |
| 4815 return true; | 4822 return true; |
| 4816 } | 4823 } |
| 4817 | 4824 |
| 4818 | 4825 |
| 4819 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( | 4826 HInstruction* HOptimizedGraphBuilder::BuildLoadMonomorphic( |
| 4820 PropertyAccessInfo* info, | 4827 PropertyAccessInfo* info, |
| 4821 HValue* object, | 4828 HValue* object, |
| 4822 HInstruction* checked_object, | 4829 HInstruction* checked_object, |
| 4823 BailoutId ast_id, | 4830 BailoutId ast_id, |
| 4824 BailoutId return_id, | 4831 BailoutId return_id, |
| 4825 bool can_inline_accessor) { | 4832 bool can_inline_accessor) { |
| 4826 if (info->IsStringLength()) { | |
| 4827 return New<HLoadNamedField>( | |
| 4828 checked_object, HObjectAccess::ForStringLength()); | |
| 4829 } | |
| 4830 | 4833 |
| 4831 if (info->IsArrayLength()) { | 4834 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
| 4832 return New<HLoadNamedField>( | 4835 if (info->GetJSObjectFieldAccess(&access)) { |
| 4833 checked_object, HObjectAccess::ForArrayLength( | 4836 return New<HLoadNamedField>(checked_object, access); |
| 4834 info->map()->elements_kind())); | |
| 4835 } | |
| 4836 | |
| 4837 if (info->IsTypedArrayLength()) { | |
| 4838 return New<HLoadNamedField>( | |
| 4839 checked_object, HObjectAccess::ForTypedArrayLength()); | |
| 4840 } | 4837 } |
| 4841 | 4838 |
| 4842 HValue* checked_holder = checked_object; | 4839 HValue* checked_holder = checked_object; |
| 4843 if (info->has_holder()) { | 4840 if (info->has_holder()) { |
| 4844 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); | 4841 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); |
| 4845 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); | 4842 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); |
| 4846 } | 4843 } |
| 4847 | 4844 |
| 4848 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined(); | 4845 if (!info->lookup()->IsFound()) return graph()->GetConstantUndefined(); |
| 4849 | 4846 |
| 4850 if (info->lookup()->IsField()) { | 4847 if (info->lookup()->IsField()) { |
| 4851 return BuildLoadNamedField(checked_holder, info->access()); | 4848 return BuildLoadNamedField(checked_holder, info->access()); |
| 4852 } | 4849 } |
| 4853 | 4850 |
| 4854 if (info->lookup()->IsPropertyCallbacks()) { | 4851 if (info->lookup()->IsPropertyCallbacks()) { |
| 4855 Push(checked_object); | 4852 Push(checked_object); |
| 4856 if (FLAG_inline_accessors && | 4853 if (FLAG_inline_accessors && |
| 4857 can_inline_accessor && | 4854 can_inline_accessor && |
| 4858 TryInlineGetter(info->accessor(), ast_id, return_id)) { | 4855 TryInlineGetter(info->accessor(), ast_id, return_id)) { |
| 4859 return NULL; | 4856 return NULL; |
| 4860 } | 4857 } |
| 4861 Add<HPushArgument>(Pop()); | 4858 Add<HPushArgument>(Pop()); |
| 4862 return new(zone()) HCallConstantFunction(info->accessor(), 1); | 4859 return New<HCallConstantFunction>(info->accessor(), 1); |
| 4863 } | 4860 } |
| 4864 | 4861 |
| 4865 ASSERT(info->lookup()->IsConstant()); | 4862 ASSERT(info->lookup()->IsConstant()); |
| 4866 return New<HConstant>(info->constant()); | 4863 return New<HConstant>(info->constant()); |
| 4867 } | 4864 } |
| 4868 | 4865 |
| 4869 | 4866 |
| 4870 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 4867 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
| 4871 int position, | 4868 int position, |
| 4872 BailoutId ast_id, | 4869 BailoutId ast_id, |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5148 Handle<JSObject> holder; | 5145 Handle<JSObject> holder; |
| 5149 if (LookupSetter(map, name, &setter, &holder)) { | 5146 if (LookupSetter(map, name, &setter, &holder)) { |
| 5150 AddCheckConstantFunction(holder, object, map); | 5147 AddCheckConstantFunction(holder, object, map); |
| 5151 if (FLAG_inline_accessors && | 5148 if (FLAG_inline_accessors && |
| 5152 TryInlineSetter(setter, ast_id, return_id, value)) { | 5149 TryInlineSetter(setter, ast_id, return_id, value)) { |
| 5153 return; | 5150 return; |
| 5154 } | 5151 } |
| 5155 Drop(2); | 5152 Drop(2); |
| 5156 Add<HPushArgument>(object); | 5153 Add<HPushArgument>(object); |
| 5157 Add<HPushArgument>(value); | 5154 Add<HPushArgument>(value); |
| 5158 instr = new(zone()) HCallConstantFunction(setter, 2); | 5155 instr = New<HCallConstantFunction>(setter, 2); |
| 5159 } else { | 5156 } else { |
| 5160 Drop(2); | 5157 Drop(2); |
| 5161 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | 5158 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
| 5162 name, | 5159 name, |
| 5163 value, | 5160 value, |
| 5164 map)); | 5161 map)); |
| 5165 } | 5162 } |
| 5166 } else if (types != NULL && types->length() > 1) { | 5163 } else if (types != NULL && types->length() > 1) { |
| 5167 Drop(2); | 5164 Drop(2); |
| 5168 return HandlePolymorphicStoreNamedField( | 5165 return HandlePolymorphicStoreNamedField( |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5489 // We don't optimize functions with invalid left-hand sides in | 5486 // We don't optimize functions with invalid left-hand sides in |
| 5490 // assignments, count operations, or for-in. Consequently throw can | 5487 // assignments, count operations, or for-in. Consequently throw can |
| 5491 // currently only occur in an effect context. | 5488 // currently only occur in an effect context. |
| 5492 ASSERT(ast_context()->IsEffect()); | 5489 ASSERT(ast_context()->IsEffect()); |
| 5493 CHECK_ALIVE(VisitForValue(expr->exception())); | 5490 CHECK_ALIVE(VisitForValue(expr->exception())); |
| 5494 | 5491 |
| 5495 HValue* value = environment()->Pop(); | 5492 HValue* value = environment()->Pop(); |
| 5496 HThrow* instr = Add<HThrow>(value); | 5493 HThrow* instr = Add<HThrow>(value); |
| 5497 instr->set_position(expr->position()); | 5494 instr->set_position(expr->position()); |
| 5498 Add<HSimulate>(expr->id()); | 5495 Add<HSimulate>(expr->id()); |
| 5496 |
| 5497 // If the throw definitely exits the function, we can finish with a dummy |
| 5498 // control flow at this point. This is not the case if the throw is inside |
| 5499 // an inlined function which may be replaced. |
| 5500 if (call_context() == NULL) { |
| 5501 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 5502 set_current_block(NULL); |
| 5503 } |
| 5499 } | 5504 } |
| 5500 | 5505 |
| 5501 | 5506 |
| 5502 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 5507 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 5503 HObjectAccess access) { | 5508 HObjectAccess access) { |
| 5504 if (FLAG_track_double_fields && access.representation().IsDouble()) { | 5509 if (FLAG_track_double_fields && access.representation().IsDouble()) { |
| 5505 // load the heap number | 5510 // load the heap number |
| 5506 HLoadNamedField* heap_number = Add<HLoadNamedField>( | 5511 HLoadNamedField* heap_number = Add<HLoadNamedField>( |
| 5507 object, access.WithRepresentation(Representation::Tagged())); | 5512 object, access.WithRepresentation(Representation::Tagged())); |
| 5508 heap_number->set_type(HType::HeapNumber()); | 5513 heap_number->set_type(HType::HeapNumber()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 5532 Property* expr) { | 5537 Property* expr) { |
| 5533 if (expr->IsUninitialized()) { | 5538 if (expr->IsUninitialized()) { |
| 5534 Add<HDeoptimize>("Insufficient type feedback for generic named load", | 5539 Add<HDeoptimize>("Insufficient type feedback for generic named load", |
| 5535 Deoptimizer::SOFT); | 5540 Deoptimizer::SOFT); |
| 5536 } | 5541 } |
| 5537 HValue* context = environment()->context(); | 5542 HValue* context = environment()->context(); |
| 5538 return new(zone()) HLoadNamedGeneric(context, object, name); | 5543 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 5539 } | 5544 } |
| 5540 | 5545 |
| 5541 | 5546 |
| 5542 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | |
| 5543 HValue* object, | |
| 5544 Handle<Map> map, | |
| 5545 Handle<JSFunction> getter, | |
| 5546 Handle<JSObject> holder) { | |
| 5547 AddCheckConstantFunction(holder, object, map); | |
| 5548 Add<HPushArgument>(object); | |
| 5549 return new(zone()) HCallConstantFunction(getter, 1); | |
| 5550 } | |
| 5551 | |
| 5552 | 5547 |
| 5553 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 5548 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| 5554 HValue* key) { | 5549 HValue* key) { |
| 5555 HValue* context = environment()->context(); | 5550 HValue* context = environment()->context(); |
| 5556 return new(zone()) HLoadKeyedGeneric(context, object, key); | 5551 return new(zone()) HLoadKeyedGeneric(context, object, key); |
| 5557 } | 5552 } |
| 5558 | 5553 |
| 5559 | 5554 |
| 5560 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { | 5555 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { |
| 5561 // Loads from a "stock" fast holey double arrays can elide the hole check. | 5556 // Loads from a "stock" fast holey double arrays can elide the hole check. |
| (...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6148 Handle<JSFunction> caller = current_info()->closure(); | 6143 Handle<JSFunction> caller = current_info()->closure(); |
| 6149 SmartArrayPointer<char> caller_name = | 6144 SmartArrayPointer<char> caller_name = |
| 6150 caller->shared()->DebugName()->ToCString(); | 6145 caller->shared()->DebugName()->ToCString(); |
| 6151 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6146 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 6152 *name->ToCString(), *caller_name); | 6147 *name->ToCString(), *caller_name); |
| 6153 } | 6148 } |
| 6154 | 6149 |
| 6155 if (!TryInlineCall(expr)) { | 6150 if (!TryInlineCall(expr)) { |
| 6156 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6151 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 6157 HCallConstantFunction* call = | 6152 HCallConstantFunction* call = |
| 6158 new(zone()) HCallConstantFunction(expr->target(), argument_count); | 6153 New<HCallConstantFunction>(expr->target(), argument_count); |
| 6159 call->set_position(expr->position()); | 6154 call->set_position(expr->position()); |
| 6160 PreProcessCall(call); | 6155 PreProcessCall(call); |
| 6161 AddInstruction(call); | 6156 AddInstruction(call); |
| 6162 if (!ast_context()->IsEffect()) Push(call); | 6157 if (!ast_context()->IsEffect()) Push(call); |
| 6163 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 6158 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 6164 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6159 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 6165 } | 6160 } |
| 6166 | 6161 |
| 6167 return true; | 6162 return true; |
| 6168 } | 6163 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6265 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6260 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
| 6266 *name->ToCString(), | 6261 *name->ToCString(), |
| 6267 *caller_name); | 6262 *caller_name); |
| 6268 } | 6263 } |
| 6269 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 6264 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { |
| 6270 // Trying to inline will signal that we should bailout from the | 6265 // Trying to inline will signal that we should bailout from the |
| 6271 // entire compilation by setting stack overflow on the visitor. | 6266 // entire compilation by setting stack overflow on the visitor. |
| 6272 if (HasStackOverflow()) return; | 6267 if (HasStackOverflow()) return; |
| 6273 } else { | 6268 } else { |
| 6274 HCallConstantFunction* call = | 6269 HCallConstantFunction* call = |
| 6275 new(zone()) HCallConstantFunction(expr->target(), argument_count); | 6270 New<HCallConstantFunction>(expr->target(), argument_count); |
| 6276 call->set_position(expr->position()); | 6271 call->set_position(expr->position()); |
| 6277 PreProcessCall(call); | 6272 PreProcessCall(call); |
| 6278 AddInstruction(call); | 6273 AddInstruction(call); |
| 6279 if (!ast_context()->IsEffect()) Push(call); | 6274 if (!ast_context()->IsEffect()) Push(call); |
| 6280 } | 6275 } |
| 6281 | 6276 |
| 6282 if (current_block() != NULL) current_block()->Goto(join); | 6277 if (current_block() != NULL) current_block()->Goto(join); |
| 6283 set_current_block(if_false); | 6278 set_current_block(if_false); |
| 6284 } | 6279 } |
| 6285 | 6280 |
| 6286 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6281 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 6287 // know about and do not want to handle ones we've never seen. Otherwise | 6282 // know about and do not want to handle ones we've never seen. Otherwise |
| 6288 // use a generic IC. | 6283 // use a generic IC. |
| 6289 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6284 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 6290 // Because the deopt may be the only path in the polymorphic call, make sure | 6285 // Because the deopt may be the only path in the polymorphic call, make sure |
| 6291 // that the environment stack matches the depth on deopt that it otherwise | 6286 // that the environment stack matches the depth on deopt that it otherwise |
| 6292 // would have had after a successful call. | 6287 // would have had after a successful call. |
| 6293 Drop(argument_count); | 6288 Drop(argument_count); |
| 6294 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 6289 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
| 6295 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); | 6290 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); |
| 6296 } else { | 6291 } else { |
| 6297 HValue* context = environment()->context(); | 6292 HCallNamed* call = New<HCallNamed>(name, argument_count); |
| 6298 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); | |
| 6299 call->set_position(expr->position()); | 6293 call->set_position(expr->position()); |
| 6300 PreProcessCall(call); | 6294 PreProcessCall(call); |
| 6301 | 6295 |
| 6302 if (join != NULL) { | 6296 if (join != NULL) { |
| 6303 AddInstruction(call); | 6297 AddInstruction(call); |
| 6304 if (!ast_context()->IsEffect()) Push(call); | 6298 if (!ast_context()->IsEffect()) Push(call); |
| 6305 current_block()->Goto(join); | 6299 current_block()->Goto(join); |
| 6306 } else { | 6300 } else { |
| 6307 return ast_context()->ReturnInstruction(call, expr->id()); | 6301 return ast_context()->ReturnInstruction(call, expr->id()); |
| 6308 } | 6302 } |
| (...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7047 | 7041 |
| 7048 CHECK_ALIVE(VisitForValue(prop->key())); | 7042 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7049 // Push receiver and key like the non-optimized code generator expects it. | 7043 // Push receiver and key like the non-optimized code generator expects it. |
| 7050 HValue* key = Pop(); | 7044 HValue* key = Pop(); |
| 7051 HValue* receiver = Pop(); | 7045 HValue* receiver = Pop(); |
| 7052 Push(key); | 7046 Push(key); |
| 7053 Push(receiver); | 7047 Push(receiver); |
| 7054 | 7048 |
| 7055 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7049 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 7056 | 7050 |
| 7057 HValue* context = environment()->context(); | 7051 call = New<HCallKeyed>(key, argument_count); |
| 7058 call = new(zone()) HCallKeyed(context, key, argument_count); | |
| 7059 call->set_position(expr->position()); | 7052 call->set_position(expr->position()); |
| 7060 Drop(argument_count + 1); // 1 is the key. | 7053 Drop(argument_count + 1); // 1 is the key. |
| 7061 return ast_context()->ReturnInstruction(call, expr->id()); | 7054 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7062 } | 7055 } |
| 7063 | 7056 |
| 7064 // Named function call. | 7057 // Named function call. |
| 7065 if (TryCallApply(expr)) return; | 7058 if (TryCallApply(expr)) return; |
| 7066 | 7059 |
| 7067 CHECK_ALIVE(VisitForValue(prop->obj())); | 7060 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7068 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7061 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 7087 PrintF("\n"); | 7080 PrintF("\n"); |
| 7088 } | 7081 } |
| 7089 return; | 7082 return; |
| 7090 } | 7083 } |
| 7091 | 7084 |
| 7092 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || | 7085 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || |
| 7093 expr->check_type() != RECEIVER_MAP_CHECK) { | 7086 expr->check_type() != RECEIVER_MAP_CHECK) { |
| 7094 // When the target has a custom call IC generator, use the IC, | 7087 // When the target has a custom call IC generator, use the IC, |
| 7095 // because it is likely to generate better code. Also use the IC | 7088 // because it is likely to generate better code. Also use the IC |
| 7096 // when a primitive receiver check is required. | 7089 // when a primitive receiver check is required. |
| 7097 HValue* context = environment()->context(); | 7090 call = PreProcessCall(New<HCallNamed>(name, argument_count)); |
| 7098 call = PreProcessCall( | |
| 7099 new(zone()) HCallNamed(context, name, argument_count)); | |
| 7100 } else { | 7091 } else { |
| 7101 AddCheckConstantFunction(expr->holder(), receiver, map); | 7092 AddCheckConstantFunction(expr->holder(), receiver, map); |
| 7102 | 7093 |
| 7103 if (TryInlineCall(expr)) return; | 7094 if (TryInlineCall(expr)) return; |
| 7104 call = PreProcessCall( | 7095 call = PreProcessCall( |
| 7105 new(zone()) HCallConstantFunction(expr->target(), | 7096 New<HCallConstantFunction>(expr->target(), argument_count)); |
| 7106 argument_count)); | |
| 7107 } | 7097 } |
| 7108 } else if (types != NULL && types->length() > 1) { | 7098 } else if (types != NULL && types->length() > 1) { |
| 7109 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 7099 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
| 7110 HandlePolymorphicCallNamed(expr, receiver, types, name); | 7100 HandlePolymorphicCallNamed(expr, receiver, types, name); |
| 7111 return; | 7101 return; |
| 7112 | 7102 |
| 7113 } else { | 7103 } else { |
| 7114 HValue* context = environment()->context(); | 7104 call = PreProcessCall(New<HCallNamed>(name, argument_count)); |
| 7115 call = PreProcessCall( | |
| 7116 new(zone()) HCallNamed(context, name, argument_count)); | |
| 7117 } | 7105 } |
| 7118 | 7106 |
| 7119 } else { | 7107 } else { |
| 7120 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7108 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 7121 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 7109 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
| 7122 return Bailout(kPossibleDirectCallToEval); | 7110 return Bailout(kPossibleDirectCallToEval); |
| 7123 } | 7111 } |
| 7124 | 7112 |
| 7125 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 7113 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
| 7126 if (global_call) { | 7114 if (global_call) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7166 } | 7154 } |
| 7167 if (TryInlineCall(expr)) return; | 7155 if (TryInlineCall(expr)) return; |
| 7168 | 7156 |
| 7169 if (expr->target().is_identical_to(current_info()->closure())) { | 7157 if (expr->target().is_identical_to(current_info()->closure())) { |
| 7170 graph()->MarkRecursive(); | 7158 graph()->MarkRecursive(); |
| 7171 } | 7159 } |
| 7172 | 7160 |
| 7173 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { | 7161 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { |
| 7174 // When the target has a custom call IC generator, use the IC, | 7162 // When the target has a custom call IC generator, use the IC, |
| 7175 // because it is likely to generate better code. | 7163 // because it is likely to generate better code. |
| 7176 HValue* context = environment()->context(); | 7164 call = PreProcessCall(New<HCallNamed>(var->name(), argument_count)); |
| 7177 call = PreProcessCall( | |
| 7178 new(zone()) HCallNamed(context, var->name(), argument_count)); | |
| 7179 } else { | 7165 } else { |
| 7180 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 7166 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
| 7181 argument_count)); | 7167 argument_count)); |
| 7182 } | 7168 } |
| 7183 } else { | 7169 } else { |
| 7184 HGlobalObject* receiver = Add<HGlobalObject>(); | 7170 HGlobalObject* receiver = Add<HGlobalObject>(); |
| 7185 PushAndAdd(New<HPushArgument>(receiver)); | 7171 PushAndAdd(New<HPushArgument>(receiver)); |
| 7186 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7172 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 7187 | 7173 |
| 7188 call = New<HCallGlobal>(var->name(), argument_count); | 7174 call = New<HCallGlobal>(var->name(), argument_count); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7242 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && | 7228 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && |
| 7243 constructor->initial_map()->InitialPropertiesLength() == 0; | 7229 constructor->initial_map()->InitialPropertiesLength() == 0; |
| 7244 } | 7230 } |
| 7245 | 7231 |
| 7246 | 7232 |
| 7247 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 7233 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
| 7248 ASSERT(!HasStackOverflow()); | 7234 ASSERT(!HasStackOverflow()); |
| 7249 ASSERT(current_block() != NULL); | 7235 ASSERT(current_block() != NULL); |
| 7250 ASSERT(current_block()->HasPredecessor()); | 7236 ASSERT(current_block()->HasPredecessor()); |
| 7251 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 7237 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
| 7252 HValue* context = environment()->context(); | |
| 7253 Factory* factory = isolate()->factory(); | 7238 Factory* factory = isolate()->factory(); |
| 7254 | 7239 |
| 7255 if (FLAG_inline_construct && | 7240 if (FLAG_inline_construct && |
| 7256 expr->IsMonomorphic() && | 7241 expr->IsMonomorphic() && |
| 7257 IsAllocationInlineable(expr->target())) { | 7242 IsAllocationInlineable(expr->target())) { |
| 7258 // The constructor function is on the stack in the unoptimized code | 7243 // The constructor function is on the stack in the unoptimized code |
| 7259 // during evaluation of the arguments. | 7244 // during evaluation of the arguments. |
| 7260 CHECK_ALIVE(VisitForValue(expr->expression())); | 7245 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 7261 HValue* function = Top(); | 7246 HValue* function = Top(); |
| 7262 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7247 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7331 HInstruction* instr = current_block()->last(); | 7316 HInstruction* instr = current_block()->last(); |
| 7332 while (instr != initial_map_value) { | 7317 while (instr != initial_map_value) { |
| 7333 HInstruction* prev_instr = instr->previous(); | 7318 HInstruction* prev_instr = instr->previous(); |
| 7334 instr->DeleteAndReplaceWith(NULL); | 7319 instr->DeleteAndReplaceWith(NULL); |
| 7335 instr = prev_instr; | 7320 instr = prev_instr; |
| 7336 } | 7321 } |
| 7337 initial_map_value->DeleteAndReplaceWith(NULL); | 7322 initial_map_value->DeleteAndReplaceWith(NULL); |
| 7338 receiver->DeleteAndReplaceWith(NULL); | 7323 receiver->DeleteAndReplaceWith(NULL); |
| 7339 check->DeleteAndReplaceWith(NULL); | 7324 check->DeleteAndReplaceWith(NULL); |
| 7340 environment()->SetExpressionStackAt(receiver_index, function); | 7325 environment()->SetExpressionStackAt(receiver_index, function); |
| 7341 HInstruction* call = PreProcessCall( | 7326 HInstruction* call = |
| 7342 new(zone()) HCallNew(context, function, argument_count)); | 7327 PreProcessCall(New<HCallNew>(function, argument_count)); |
| 7343 call->set_position(expr->position()); | 7328 call->set_position(expr->position()); |
| 7344 return ast_context()->ReturnInstruction(call, expr->id()); | 7329 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7345 } else { | 7330 } else { |
| 7346 // The constructor function is both an operand to the instruction and an | 7331 // The constructor function is both an operand to the instruction and an |
| 7347 // argument to the construct call. | 7332 // argument to the construct call. |
| 7348 Handle<JSFunction> array_function( | 7333 Handle<JSFunction> array_function( |
| 7349 isolate()->global_context()->array_function(), isolate()); | 7334 isolate()->global_context()->array_function(), isolate()); |
| 7350 CHECK_ALIVE(VisitArgument(expr->expression())); | 7335 CHECK_ALIVE(VisitArgument(expr->expression())); |
| 7351 HValue* constructor = HPushArgument::cast(Top())->argument(); | 7336 HValue* constructor = HPushArgument::cast(Top())->argument(); |
| 7352 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7337 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 7353 HBinaryCall* call; | 7338 HBinaryCall* call; |
| 7354 if (expr->target().is_identical_to(array_function)) { | 7339 if (expr->target().is_identical_to(array_function)) { |
| 7355 Handle<Cell> cell = expr->allocation_info_cell(); | 7340 Handle<Cell> cell = expr->allocation_info_cell(); |
| 7356 Add<HCheckValue>(constructor, array_function); | 7341 Add<HCheckValue>(constructor, array_function); |
| 7357 call = new(zone()) HCallNewArray(context, constructor, argument_count, | 7342 call = New<HCallNewArray>(constructor, argument_count, |
| 7358 cell, expr->elements_kind()); | 7343 cell, expr->elements_kind()); |
| 7359 } else { | 7344 } else { |
| 7360 call = new(zone()) HCallNew(context, constructor, argument_count); | 7345 call = New<HCallNew>(constructor, argument_count); |
| 7361 } | 7346 } |
| 7362 Drop(argument_count); | 7347 Drop(argument_count); |
| 7363 call->set_position(expr->position()); | 7348 call->set_position(expr->position()); |
| 7364 return ast_context()->ReturnInstruction(call, expr->id()); | 7349 return ast_context()->ReturnInstruction(call, expr->id()); |
| 7365 } | 7350 } |
| 7366 } | 7351 } |
| 7367 | 7352 |
| 7368 | 7353 |
| 7369 // Support for generating inlined runtime functions. | 7354 // Support for generating inlined runtime functions. |
| 7370 | 7355 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7475 | 7460 |
| 7476 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { | 7461 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) { |
| 7477 CHECK_ALIVE(VisitForEffect(expr->expression())); | 7462 CHECK_ALIVE(VisitForEffect(expr->expression())); |
| 7478 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 7463 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| 7479 } | 7464 } |
| 7480 | 7465 |
| 7481 | 7466 |
| 7482 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 7467 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
| 7483 CHECK_ALIVE(VisitForTypeOf(expr->expression())); | 7468 CHECK_ALIVE(VisitForTypeOf(expr->expression())); |
| 7484 HValue* value = Pop(); | 7469 HValue* value = Pop(); |
| 7485 HValue* context = environment()->context(); | 7470 HInstruction* instr = New<HTypeof>(value); |
| 7486 HInstruction* instr = new(zone()) HTypeof(context, value); | |
| 7487 return ast_context()->ReturnInstruction(instr, expr->id()); | 7471 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 7488 } | 7472 } |
| 7489 | 7473 |
| 7490 | 7474 |
| 7491 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 7475 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { |
| 7492 if (ast_context()->IsTest()) { | 7476 if (ast_context()->IsTest()) { |
| 7493 TestContext* context = TestContext::cast(ast_context()); | 7477 TestContext* context = TestContext::cast(ast_context()); |
| 7494 VisitForControl(expr->expression(), | 7478 VisitForControl(expr->expression(), |
| 7495 context->if_false(), | 7479 context->if_false(), |
| 7496 context->if_true()); | 7480 context->if_true()); |
| (...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8265 | 8249 |
| 8266 // If the target is not null we have found a known global function that is | 8250 // If the target is not null we have found a known global function that is |
| 8267 // assumed to stay the same for this instanceof. | 8251 // assumed to stay the same for this instanceof. |
| 8268 if (target.is_null()) { | 8252 if (target.is_null()) { |
| 8269 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); | 8253 HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); |
| 8270 result->set_position(expr->position()); | 8254 result->set_position(expr->position()); |
| 8271 return ast_context()->ReturnInstruction(result, expr->id()); | 8255 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8272 } else { | 8256 } else { |
| 8273 Add<HCheckValue>(right, target); | 8257 Add<HCheckValue>(right, target); |
| 8274 HInstanceOfKnownGlobal* result = | 8258 HInstanceOfKnownGlobal* result = |
| 8275 new(zone()) HInstanceOfKnownGlobal(context, left, target); | 8259 New<HInstanceOfKnownGlobal>(left, target); |
| 8276 result->set_position(expr->position()); | 8260 result->set_position(expr->position()); |
| 8277 return ast_context()->ReturnInstruction(result, expr->id()); | 8261 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8278 } | 8262 } |
| 8279 | 8263 |
| 8280 // Code below assumes that we don't fall through. | 8264 // Code below assumes that we don't fall through. |
| 8281 UNREACHABLE(); | 8265 UNREACHABLE(); |
| 8282 } else if (op == Token::IN) { | 8266 } else if (op == Token::IN) { |
| 8283 HValue* function = AddLoadJSBuiltin(Builtins::IN); | 8267 HValue* function = AddLoadJSBuiltin(Builtins::IN); |
| 8284 Add<HPushArgument>(left); | 8268 Add<HPushArgument>(left); |
| 8285 Add<HPushArgument>(right); | 8269 Add<HPushArgument>(right); |
| 8286 // TODO(olivf) InvokeFunction produces a check for the parameter count, | 8270 // TODO(olivf) InvokeFunction produces a check for the parameter count, |
| 8287 // even though we are certain to pass the correct number of arguments here. | 8271 // even though we are certain to pass the correct number of arguments here. |
| 8288 HInstruction* result = new(zone()) HInvokeFunction(context, function, 2); | 8272 HInstruction* result = New<HInvokeFunction>(function, 2); |
| 8289 result->set_position(expr->position()); | 8273 result->set_position(expr->position()); |
| 8290 return ast_context()->ReturnInstruction(result, expr->id()); | 8274 return ast_context()->ReturnInstruction(result, expr->id()); |
| 8291 } | 8275 } |
| 8292 | 8276 |
| 8293 // Cases handled below depend on collected type feedback. They should | 8277 // Cases handled below depend on collected type feedback. They should |
| 8294 // soft deoptimize when there is no type feedback. | 8278 // soft deoptimize when there is no type feedback. |
| 8295 if (combined_type->Is(Type::None())) { | 8279 if (combined_type->Is(Type::None())) { |
| 8296 Add<HDeoptimize>("Insufficient type feedback for combined type " | 8280 Add<HDeoptimize>("Insufficient type feedback for combined type " |
| 8297 "of binary operation", | 8281 "of binary operation", |
| 8298 Deoptimizer::SOFT); | 8282 Deoptimizer::SOFT); |
| (...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9077 } | 9061 } |
| 9078 | 9062 |
| 9079 | 9063 |
| 9080 // Fast support for StringAdd. | 9064 // Fast support for StringAdd. |
| 9081 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 9065 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
| 9082 ASSERT_EQ(2, call->arguments()->length()); | 9066 ASSERT_EQ(2, call->arguments()->length()); |
| 9083 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9067 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9084 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 9068 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 9085 HValue* right = Pop(); | 9069 HValue* right = Pop(); |
| 9086 HValue* left = Pop(); | 9070 HValue* left = Pop(); |
| 9087 HValue* context = environment()->context(); | 9071 HInstruction* result = New<HStringAdd>(left, right, STRING_ADD_CHECK_BOTH); |
| 9088 HInstruction* result = HStringAdd::New( | |
| 9089 zone(), context, left, right, STRING_ADD_CHECK_BOTH); | |
| 9090 return ast_context()->ReturnInstruction(result, call->id()); | 9072 return ast_context()->ReturnInstruction(result, call->id()); |
| 9091 } | 9073 } |
| 9092 | 9074 |
| 9093 | 9075 |
| 9094 // Fast support for SubString. | 9076 // Fast support for SubString. |
| 9095 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 9077 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
| 9096 ASSERT_EQ(3, call->arguments()->length()); | 9078 ASSERT_EQ(3, call->arguments()->length()); |
| 9097 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9079 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9098 HValue* context = environment()->context(); | 9080 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); |
| 9099 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); | |
| 9100 Drop(3); | 9081 Drop(3); |
| 9101 return ast_context()->ReturnInstruction(result, call->id()); | 9082 return ast_context()->ReturnInstruction(result, call->id()); |
| 9102 } | 9083 } |
| 9103 | 9084 |
| 9104 | 9085 |
| 9105 // Fast support for StringCompare. | 9086 // Fast support for StringCompare. |
| 9106 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 9087 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
| 9107 ASSERT_EQ(2, call->arguments()->length()); | 9088 ASSERT_EQ(2, call->arguments()->length()); |
| 9108 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9089 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9109 HValue* context = environment()->context(); | 9090 HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2); |
| 9110 HCallStub* result = | |
| 9111 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); | |
| 9112 Drop(2); | 9091 Drop(2); |
| 9113 return ast_context()->ReturnInstruction(result, call->id()); | 9092 return ast_context()->ReturnInstruction(result, call->id()); |
| 9114 } | 9093 } |
| 9115 | 9094 |
| 9116 | 9095 |
| 9117 // Support for direct calls from JavaScript to native RegExp code. | 9096 // Support for direct calls from JavaScript to native RegExp code. |
| 9118 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 9097 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
| 9119 ASSERT_EQ(4, call->arguments()->length()); | 9098 ASSERT_EQ(4, call->arguments()->length()); |
| 9120 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9099 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9121 HValue* context = environment()->context(); | 9100 HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4); |
| 9122 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); | |
| 9123 Drop(4); | 9101 Drop(4); |
| 9124 return ast_context()->ReturnInstruction(result, call->id()); | 9102 return ast_context()->ReturnInstruction(result, call->id()); |
| 9125 } | 9103 } |
| 9126 | 9104 |
| 9127 | 9105 |
| 9128 // Construct a RegExp exec result with two in-object properties. | 9106 // Construct a RegExp exec result with two in-object properties. |
| 9129 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 9107 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
| 9130 ASSERT_EQ(3, call->arguments()->length()); | 9108 ASSERT_EQ(3, call->arguments()->length()); |
| 9131 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9109 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9132 HValue* context = environment()->context(); | 9110 HCallStub* result = New<HCallStub>(CodeStub::RegExpConstructResult, 3); |
| 9133 HCallStub* result = | |
| 9134 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | |
| 9135 Drop(3); | 9111 Drop(3); |
| 9136 return ast_context()->ReturnInstruction(result, call->id()); | 9112 return ast_context()->ReturnInstruction(result, call->id()); |
| 9137 } | 9113 } |
| 9138 | 9114 |
| 9139 | 9115 |
| 9140 // Support for fast native caches. | 9116 // Support for fast native caches. |
| 9141 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9117 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
| 9142 return Bailout(kInlinedRuntimeFunctionGetFromCache); | 9118 return Bailout(kInlinedRuntimeFunctionGetFromCache); |
| 9143 } | 9119 } |
| 9144 | 9120 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9202 HValue* right = Pop(); | 9178 HValue* right = Pop(); |
| 9203 HValue* left = Pop(); | 9179 HValue* left = Pop(); |
| 9204 HInstruction* result = HPower::New(zone(), context(), left, right); | 9180 HInstruction* result = HPower::New(zone(), context(), left, right); |
| 9205 return ast_context()->ReturnInstruction(result, call->id()); | 9181 return ast_context()->ReturnInstruction(result, call->id()); |
| 9206 } | 9182 } |
| 9207 | 9183 |
| 9208 | 9184 |
| 9209 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { | 9185 void HOptimizedGraphBuilder::GenerateMathSin(CallRuntime* call) { |
| 9210 ASSERT_EQ(1, call->arguments()->length()); | 9186 ASSERT_EQ(1, call->arguments()->length()); |
| 9211 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9187 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9212 HValue* context = environment()->context(); | 9188 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1); |
| 9213 HCallStub* result = | |
| 9214 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | |
| 9215 result->set_transcendental_type(TranscendentalCache::SIN); | 9189 result->set_transcendental_type(TranscendentalCache::SIN); |
| 9216 Drop(1); | 9190 Drop(1); |
| 9217 return ast_context()->ReturnInstruction(result, call->id()); | 9191 return ast_context()->ReturnInstruction(result, call->id()); |
| 9218 } | 9192 } |
| 9219 | 9193 |
| 9220 | 9194 |
| 9221 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) { | 9195 void HOptimizedGraphBuilder::GenerateMathCos(CallRuntime* call) { |
| 9222 ASSERT_EQ(1, call->arguments()->length()); | 9196 ASSERT_EQ(1, call->arguments()->length()); |
| 9223 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9197 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9224 HValue* context = environment()->context(); | 9198 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1); |
| 9225 HCallStub* result = | |
| 9226 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | |
| 9227 result->set_transcendental_type(TranscendentalCache::COS); | 9199 result->set_transcendental_type(TranscendentalCache::COS); |
| 9228 Drop(1); | 9200 Drop(1); |
| 9229 return ast_context()->ReturnInstruction(result, call->id()); | 9201 return ast_context()->ReturnInstruction(result, call->id()); |
| 9230 } | 9202 } |
| 9231 | 9203 |
| 9232 | 9204 |
| 9233 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) { | 9205 void HOptimizedGraphBuilder::GenerateMathTan(CallRuntime* call) { |
| 9234 ASSERT_EQ(1, call->arguments()->length()); | 9206 ASSERT_EQ(1, call->arguments()->length()); |
| 9235 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9207 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9236 HValue* context = environment()->context(); | 9208 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1); |
| 9237 HCallStub* result = | |
| 9238 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | |
| 9239 result->set_transcendental_type(TranscendentalCache::TAN); | 9209 result->set_transcendental_type(TranscendentalCache::TAN); |
| 9240 Drop(1); | 9210 Drop(1); |
| 9241 return ast_context()->ReturnInstruction(result, call->id()); | 9211 return ast_context()->ReturnInstruction(result, call->id()); |
| 9242 } | 9212 } |
| 9243 | 9213 |
| 9244 | 9214 |
| 9245 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { | 9215 void HOptimizedGraphBuilder::GenerateMathLog(CallRuntime* call) { |
| 9246 ASSERT_EQ(1, call->arguments()->length()); | 9216 ASSERT_EQ(1, call->arguments()->length()); |
| 9247 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9217 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 9248 HValue* context = environment()->context(); | 9218 HCallStub* result = New<HCallStub>(CodeStub::TranscendentalCache, 1); |
| 9249 HCallStub* result = | |
| 9250 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | |
| 9251 result->set_transcendental_type(TranscendentalCache::LOG); | 9219 result->set_transcendental_type(TranscendentalCache::LOG); |
| 9252 Drop(1); | 9220 Drop(1); |
| 9253 return ast_context()->ReturnInstruction(result, call->id()); | 9221 return ast_context()->ReturnInstruction(result, call->id()); |
| 9254 } | 9222 } |
| 9255 | 9223 |
| 9256 | 9224 |
| 9257 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 9225 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
| 9258 ASSERT(call->arguments()->length() == 1); | 9226 ASSERT(call->arguments()->length() == 1); |
| 9259 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9227 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9260 HValue* value = Pop(); | 9228 HValue* value = Pop(); |
| 9261 HValue* context = environment()->context(); | 9229 HInstruction* result = New<HUnaryMathOperation>(value, kMathSqrt); |
| 9262 HInstruction* result = | |
| 9263 HUnaryMathOperation::New(zone(), context, value, kMathSqrt); | |
| 9264 return ast_context()->ReturnInstruction(result, call->id()); | 9230 return ast_context()->ReturnInstruction(result, call->id()); |
| 9265 } | 9231 } |
| 9266 | 9232 |
| 9267 | 9233 |
| 9268 // Check whether two RegExps are equivalent | 9234 // Check whether two RegExps are equivalent |
| 9269 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 9235 void HOptimizedGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
| 9270 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent); | 9236 return Bailout(kInlinedRuntimeFunctionIsRegExpEquivalent); |
| 9271 } | 9237 } |
| 9272 | 9238 |
| 9273 | 9239 |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9909 if (ShouldProduceTraceOutput()) { | 9875 if (ShouldProduceTraceOutput()) { |
| 9910 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9876 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9911 } | 9877 } |
| 9912 | 9878 |
| 9913 #ifdef DEBUG | 9879 #ifdef DEBUG |
| 9914 graph_->Verify(false); // No full verify. | 9880 graph_->Verify(false); // No full verify. |
| 9915 #endif | 9881 #endif |
| 9916 } | 9882 } |
| 9917 | 9883 |
| 9918 } } // namespace v8::internal | 9884 } } // namespace v8::internal |
| OLD | NEW |