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

Side by Side Diff: src/hydrogen.cc

Issue 148153010: Synchronize with r15701. (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-canonicalize.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 16 matching lines...) Expand all
27 27
28 #include "hydrogen.h" 28 #include "hydrogen.h"
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-canonicalize.h"
37 #include "hydrogen-dce.h" 38 #include "hydrogen-dce.h"
39 #include "hydrogen-dehoist.h"
40 #include "hydrogen-deoptimizing-mark.h"
38 #include "hydrogen-environment-liveness.h" 41 #include "hydrogen-environment-liveness.h"
39 #include "hydrogen-escape-analysis.h" 42 #include "hydrogen-escape-analysis.h"
40 #include "hydrogen-infer-representation.h" 43 #include "hydrogen-infer-representation.h"
41 #include "hydrogen-infer-types.h" 44 #include "hydrogen-infer-types.h"
42 #include "hydrogen-gvn.h" 45 #include "hydrogen-gvn.h"
46 #include "hydrogen-minus-zero.h"
43 #include "hydrogen-osr.h" 47 #include "hydrogen-osr.h"
44 #include "hydrogen-range-analysis.h" 48 #include "hydrogen-range-analysis.h"
45 #include "hydrogen-redundant-phi.h" 49 #include "hydrogen-redundant-phi.h"
50 #include "hydrogen-removable-simulates.h"
46 #include "hydrogen-representation-changes.h" 51 #include "hydrogen-representation-changes.h"
47 #include "hydrogen-sce.h" 52 #include "hydrogen-sce.h"
48 #include "hydrogen-uint32-analysis.h" 53 #include "hydrogen-uint32-analysis.h"
49 #include "lithium-allocator.h" 54 #include "lithium-allocator.h"
50 #include "parser.h" 55 #include "parser.h"
51 #include "scopeinfo.h" 56 #include "scopeinfo.h"
52 #include "scopes.h" 57 #include "scopes.h"
53 #include "stub-cache.h" 58 #include "stub-cache.h"
54 #include "typing.h" 59 #include "typing.h"
55 60
(...skipping 1081 matching lines...) Expand 10 before | Expand all | Expand 10 after
1137 1142
1138 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, 1143 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object,
1139 HValue* elements, 1144 HValue* elements,
1140 ElementsKind kind, 1145 ElementsKind kind,
1141 HValue* length, 1146 HValue* length,
1142 HValue* key, 1147 HValue* key,
1143 bool is_js_array) { 1148 bool is_js_array) {
1144 Zone* zone = this->zone(); 1149 Zone* zone = this->zone();
1145 IfBuilder length_checker(this); 1150 IfBuilder length_checker(this);
1146 1151
1147 length_checker.If<HCompareNumericAndBranch>(length, key, Token::EQ); 1152 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
1153 length_checker.If<HCompareNumericAndBranch>(key, length, token);
1154
1148 length_checker.Then(); 1155 length_checker.Then();
1149 1156
1150 HValue* current_capacity = AddLoadFixedArrayLength(elements); 1157 HValue* current_capacity = AddLoadFixedArrayLength(elements);
1151 1158
1152 IfBuilder capacity_checker(this); 1159 IfBuilder capacity_checker(this);
1153 1160
1154 capacity_checker.If<HCompareNumericAndBranch>(length, current_capacity, 1161 capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
1155 Token::EQ); 1162 Token::GTE);
1156 capacity_checker.Then(); 1163 capacity_checker.Then();
1157 1164
1158 HValue* context = environment()->LookupContext(); 1165 HValue* context = environment()->LookupContext();
1159 1166
1160 HValue* new_capacity = 1167 HValue* new_capacity = BuildNewElementsCapacity(context, key);
1161 BuildNewElementsCapacity(context, current_capacity);
1162 1168
1163 HValue* new_elements = BuildGrowElementsCapacity(object, elements, 1169 HValue* new_elements = BuildGrowElementsCapacity(object, elements,
1164 kind, kind, length, 1170 kind, kind, length,
1165 new_capacity); 1171 new_capacity);
1166 1172
1167 environment()->Push(new_elements); 1173 environment()->Push(new_elements);
1168 capacity_checker.Else(); 1174 capacity_checker.Else();
1169 1175
1170 environment()->Push(elements); 1176 environment()->Push(elements);
1171 capacity_checker.End(); 1177 capacity_checker.End();
1172 1178
1173 if (is_js_array) { 1179 if (is_js_array) {
1174 HValue* new_length = AddInstruction( 1180 HValue* new_length = AddInstruction(
1175 HAdd::New(zone, context, length, graph_->GetConstant1())); 1181 HAdd::New(zone, context, key, graph_->GetConstant1()));
1176 new_length->ClearFlag(HValue::kCanOverflow); 1182 new_length->ClearFlag(HValue::kCanOverflow);
1177 1183
1178 Representation representation = IsFastElementsKind(kind) 1184 Representation representation = IsFastElementsKind(kind)
1179 ? Representation::Smi() : Representation::Tagged(); 1185 ? Representation::Smi() : Representation::Tagged();
1180 AddStore(object, HObjectAccess::ForArrayLength(), new_length, 1186 AddStore(object, HObjectAccess::ForArrayLength(), new_length,
1181 representation); 1187 representation);
1182 } 1188 }
1183 1189
1184 length_checker.Else(); 1190 length_checker.Else();
1191 Add<HBoundsCheck>(key, length);
1185 1192
1186 Add<HBoundsCheck>(key, length);
1187 environment()->Push(elements); 1193 environment()->Push(elements);
1188
1189 length_checker.End(); 1194 length_checker.End();
1190 1195
1191 return environment()->Pop(); 1196 return environment()->Pop();
1192 } 1197 }
1193 1198
1194 1199
1195 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object, 1200 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
1196 HValue* elements, 1201 HValue* elements,
1197 ElementsKind kind, 1202 ElementsKind kind,
1198 HValue* length) { 1203 HValue* length) {
(...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after
2084 DisallowHeapAllocation no_gc; 2089 DisallowHeapAllocation no_gc;
2085 ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread()); 2090 ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
2086 for (int i = 0; i < blocks()->length(); ++i) { 2091 for (int i = 0; i < blocks()->length(); ++i) {
2087 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { 2092 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
2088 it.Current()->FinalizeUniqueValueId(); 2093 it.Current()->FinalizeUniqueValueId();
2089 } 2094 }
2090 } 2095 }
2091 } 2096 }
2092 2097
2093 2098
2094 void HGraph::Canonicalize() {
2095 HPhase phase("H_Canonicalize", this);
2096 // Before removing no-op instructions, save their semantic value.
2097 // We must be careful not to set the flag unnecessarily, because GVN
2098 // cannot identify two instructions when their flag value differs.
2099 for (int i = 0; i < blocks()->length(); ++i) {
2100 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
2101 HInstruction* instr = it.Current();
2102 if (instr->IsArithmeticBinaryOperation() &&
2103 instr->representation().IsInteger32() &&
2104 instr->HasAtLeastOneUseWithFlagAndNoneWithout(
2105 HInstruction::kTruncatingToInt32)) {
2106 instr->SetFlag(HInstruction::kAllUsesTruncatingToInt32);
2107 }
2108 }
2109 }
2110 // Perform actual Canonicalization pass.
2111 for (int i = 0; i < blocks()->length(); ++i) {
2112 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
2113 HInstruction* instr = it.Current();
2114 HValue* value = instr->Canonicalize();
2115 if (value != instr) instr->DeleteAndReplaceWith(value);
2116 }
2117 }
2118 }
2119
2120
2121 // Block ordering was implemented with two mutually recursive methods, 2099 // Block ordering was implemented with two mutually recursive methods,
2122 // HGraph::Postorder and HGraph::PostorderLoopBlocks. 2100 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
2123 // The recursion could lead to stack overflow so the algorithm has been 2101 // The recursion could lead to stack overflow so the algorithm has been
2124 // implemented iteratively. 2102 // implemented iteratively.
2125 // At a high level the algorithm looks like this: 2103 // At a high level the algorithm looks like this:
2126 // 2104 //
2127 // Postorder(block, loop_header) : { 2105 // Postorder(block, loop_header) : {
2128 // if (block has already been visited or is of another loop) return; 2106 // if (block has already been visited or is of another loop) return;
2129 // mark block as visited; 2107 // mark block as visited;
2130 // if (block is a loop header) { 2108 // if (block is a loop header) {
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
2445 block->AssignLoopSuccessorDominators(); 2423 block->AssignLoopSuccessorDominators();
2446 } else { 2424 } else {
2447 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { 2425 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
2448 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); 2426 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
2449 } 2427 }
2450 } 2428 }
2451 } 2429 }
2452 } 2430 }
2453 2431
2454 2432
2455 // Mark all blocks that are dominated by an unconditional soft deoptimize to
2456 // prevent code motion across those blocks.
2457 void HGraph::PropagateDeoptimizingMark() {
2458 HPhase phase("H_Propagate deoptimizing mark", this);
2459 // Skip this phase if there is nothing to be done anyway.
2460 if (!has_soft_deoptimize()) return;
2461 MarkAsDeoptimizingRecursively(entry_block());
2462 NullifyUnreachableInstructions();
2463 }
2464
2465
2466 void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
2467 for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
2468 HBasicBlock* dominated = block->dominated_blocks()->at(i);
2469 if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing();
2470 MarkAsDeoptimizingRecursively(dominated);
2471 }
2472 }
2473
2474
2475 void HGraph::NullifyUnreachableInstructions() {
2476 if (!FLAG_unreachable_code_elimination) return;
2477 int block_count = blocks_.length();
2478 for (int i = 0; i < block_count; ++i) {
2479 HBasicBlock* block = blocks_.at(i);
2480 bool nullify = false;
2481 const ZoneList<HBasicBlock*>* predecessors = block->predecessors();
2482 int predecessors_length = predecessors->length();
2483 bool all_predecessors_deoptimizing = (predecessors_length > 0);
2484 for (int j = 0; j < predecessors_length; ++j) {
2485 if (!predecessors->at(j)->IsDeoptimizing()) {
2486 all_predecessors_deoptimizing = false;
2487 break;
2488 }
2489 }
2490 if (all_predecessors_deoptimizing) nullify = true;
2491 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
2492 HInstruction* instr = it.Current();
2493 // Leave the basic structure of the graph intact.
2494 if (instr->IsBlockEntry()) continue;
2495 if (instr->IsControlInstruction()) continue;
2496 if (instr->IsSimulate()) continue;
2497 if (instr->IsEnterInlined()) continue;
2498 if (instr->IsLeaveInlined()) continue;
2499 if (nullify) {
2500 HInstruction* last_dummy = NULL;
2501 for (int j = 0; j < instr->OperandCount(); ++j) {
2502 HValue* operand = instr->OperandAt(j);
2503 // Insert an HDummyUse for each operand, unless the operand
2504 // is an HDummyUse itself. If it's even from the same block,
2505 // remember it as a potential replacement for the instruction.
2506 if (operand->IsDummyUse()) {
2507 if (operand->block() == instr->block() &&
2508 last_dummy == NULL) {
2509 last_dummy = HInstruction::cast(operand);
2510 }
2511 continue;
2512 }
2513 if (operand->IsControlInstruction()) {
2514 // Inserting a dummy use for a value that's not defined anywhere
2515 // will fail. Some instructions define fake inputs on such
2516 // values as control flow dependencies.
2517 continue;
2518 }
2519 HDummyUse* dummy = new(zone()) HDummyUse(operand);
2520 dummy->InsertBefore(instr);
2521 last_dummy = dummy;
2522 }
2523 if (last_dummy == NULL) last_dummy = GetConstant1();
2524 instr->DeleteAndReplaceWith(last_dummy);
2525 continue;
2526 }
2527 if (instr->IsSoftDeoptimize()) {
2528 ASSERT(block->IsDeoptimizing());
2529 nullify = true;
2530 }
2531 }
2532 }
2533 }
2534
2535
2536 bool HGraph::CheckArgumentsPhiUses() { 2433 bool HGraph::CheckArgumentsPhiUses() {
2537 int block_count = blocks_.length(); 2434 int block_count = blocks_.length();
2538 for (int i = 0; i < block_count; ++i) { 2435 for (int i = 0; i < block_count; ++i) {
2539 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 2436 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
2540 HPhi* phi = blocks_[i]->phis()->at(j); 2437 HPhi* phi = blocks_[i]->phis()->at(j);
2541 // We don't support phi uses of arguments for now. 2438 // We don't support phi uses of arguments for now.
2542 if (phi->CheckFlag(HValue::kIsArguments)) return false; 2439 if (phi->CheckFlag(HValue::kIsArguments)) return false;
2543 } 2440 }
2544 } 2441 }
2545 return true; 2442 return true;
(...skipping 20 matching lines...) Expand all
2566 phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone()); 2463 phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
2567 for (int i = 0; i < block_count; ++i) { 2464 for (int i = 0; i < block_count; ++i) {
2568 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 2465 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
2569 HPhi* phi = blocks_[i]->phis()->at(j); 2466 HPhi* phi = blocks_[i]->phis()->at(j);
2570 phi_list_->Add(phi, zone()); 2467 phi_list_->Add(phi, zone());
2571 } 2468 }
2572 } 2469 }
2573 } 2470 }
2574 2471
2575 2472
2576 void HGraph::MergeRemovableSimulates() {
2577 HPhase phase("H_Merge removable simulates", this);
2578 ZoneList<HSimulate*> mergelist(2, zone());
2579 for (int i = 0; i < blocks()->length(); ++i) {
2580 HBasicBlock* block = blocks()->at(i);
2581 // Make sure the merge list is empty at the start of a block.
2582 ASSERT(mergelist.is_empty());
2583 // Nasty heuristic: Never remove the first simulate in a block. This
2584 // just so happens to have a beneficial effect on register allocation.
2585 bool first = true;
2586 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
2587 HInstruction* current = it.Current();
2588 if (current->IsLeaveInlined()) {
2589 // Never fold simulates from inlined environments into simulates
2590 // in the outer environment.
2591 // (Before each HEnterInlined, there is a non-foldable HSimulate
2592 // anyway, so we get the barrier in the other direction for free.)
2593 // Simply remove all accumulated simulates without merging. This
2594 // is safe because simulates after instructions with side effects
2595 // are never added to the merge list.
2596 while (!mergelist.is_empty()) {
2597 mergelist.RemoveLast()->DeleteAndReplaceWith(NULL);
2598 }
2599 continue;
2600 }
2601 if (current->IsReturn()) {
2602 // Drop mergeable simulates in the list. This is safe because
2603 // simulates after instructions with side effects are never added
2604 // to the merge list.
2605 while (!mergelist.is_empty()) {
2606 mergelist.RemoveLast()->DeleteAndReplaceWith(NULL);
2607 }
2608 continue;
2609 }
2610 // Skip the non-simulates and the first simulate.
2611 if (!current->IsSimulate()) continue;
2612 if (first) {
2613 first = false;
2614 continue;
2615 }
2616 HSimulate* current_simulate = HSimulate::cast(current);
2617 if ((current_simulate->previous()->HasObservableSideEffects() &&
2618 !current_simulate->next()->IsSimulate()) ||
2619 !current_simulate->is_candidate_for_removal()) {
2620 // This simulate is not suitable for folding.
2621 // Fold the ones accumulated so far.
2622 current_simulate->MergeWith(&mergelist);
2623 continue;
2624 } else {
2625 // Accumulate this simulate for folding later on.
2626 mergelist.Add(current_simulate, zone());
2627 }
2628 }
2629
2630 if (!mergelist.is_empty()) {
2631 // Merge the accumulated simulates at the end of the block.
2632 HSimulate* last = mergelist.RemoveLast();
2633 last->MergeWith(&mergelist);
2634 }
2635 }
2636 }
2637
2638
2639 void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) {
2640 HValue* current = value;
2641 while (current != NULL) {
2642 if (visited->Contains(current->id())) return;
2643
2644 // For phis, we must propagate the check to all of its inputs.
2645 if (current->IsPhi()) {
2646 visited->Add(current->id());
2647 HPhi* phi = HPhi::cast(current);
2648 for (int i = 0; i < phi->OperandCount(); ++i) {
2649 PropagateMinusZeroChecks(phi->OperandAt(i), visited);
2650 }
2651 break;
2652 }
2653
2654 // For multiplication, division, and Math.min/max(), we must propagate
2655 // to the left and the right side.
2656 if (current->IsMul()) {
2657 HMul* mul = HMul::cast(current);
2658 mul->EnsureAndPropagateNotMinusZero(visited);
2659 PropagateMinusZeroChecks(mul->left(), visited);
2660 PropagateMinusZeroChecks(mul->right(), visited);
2661 } else if (current->IsDiv()) {
2662 HDiv* div = HDiv::cast(current);
2663 div->EnsureAndPropagateNotMinusZero(visited);
2664 PropagateMinusZeroChecks(div->left(), visited);
2665 PropagateMinusZeroChecks(div->right(), visited);
2666 } else if (current->IsMathMinMax()) {
2667 HMathMinMax* minmax = HMathMinMax::cast(current);
2668 visited->Add(minmax->id());
2669 PropagateMinusZeroChecks(minmax->left(), visited);
2670 PropagateMinusZeroChecks(minmax->right(), visited);
2671 }
2672
2673 current = current->EnsureAndPropagateNotMinusZero(visited);
2674 }
2675 }
2676
2677
2678 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { 2473 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) {
2679 if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return; 2474 if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return;
2680 phi->ClearFlag(HValue::kAllowUndefinedAsNaN); 2475 phi->ClearFlag(HValue::kAllowUndefinedAsNaN);
2681 for (int i = 0; i < phi->OperandCount(); ++i) { 2476 for (int i = 0; i < phi->OperandCount(); ++i) {
2682 HValue* input = phi->OperandAt(i); 2477 HValue* input = phi->OperandAt(i);
2683 if (input->IsPhi()) { 2478 if (input->IsPhi()) {
2684 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input)); 2479 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input));
2685 } 2480 }
2686 } 2481 }
2687 } 2482 }
(...skipping 12 matching lines...) Expand all
2700 HValue* use_value = it.value(); 2495 HValue* use_value = it.value();
2701 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) { 2496 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) {
2702 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); 2497 RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
2703 break; 2498 break;
2704 } 2499 }
2705 } 2500 }
2706 } 2501 }
2707 } 2502 }
2708 2503
2709 2504
2710 void HGraph::ComputeMinusZeroChecks() {
2711 HPhase phase("H_Compute minus zero checks", this);
2712 BitVector visited(GetMaximumValueID(), zone());
2713 for (int i = 0; i < blocks_.length(); ++i) {
2714 for (HInstructionIterator it(blocks_[i]); !it.Done(); it.Advance()) {
2715 HInstruction* current = it.Current();
2716 if (current->IsChange()) {
2717 HChange* change = HChange::cast(current);
2718 // Propagate flags for negative zero checks upwards from conversions
2719 // int32-to-tagged and int32-to-double.
2720 Representation from = change->value()->representation();
2721 ASSERT(from.Equals(change->from()));
2722 if (from.IsInteger32()) {
2723 ASSERT(change->to().IsTagged() ||
2724 change->to().IsDouble() ||
2725 change->to().IsSmi());
2726 ASSERT(visited.IsEmpty());
2727 PropagateMinusZeroChecks(change->value(), &visited);
2728 visited.Clear();
2729 }
2730 }
2731 }
2732 }
2733 }
2734
2735
2736 // Implementation of utility class to encapsulate the translation state for 2505 // Implementation of utility class to encapsulate the translation state for
2737 // a (possibly inlined) function. 2506 // a (possibly inlined) function.
2738 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, 2507 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
2739 CompilationInfo* info, 2508 CompilationInfo* info,
2740 InliningKind inlining_kind) 2509 InliningKind inlining_kind)
2741 : owner_(owner), 2510 : owner_(owner),
2742 compilation_info_(info), 2511 compilation_info_(info),
2743 call_context_(NULL), 2512 call_context_(NULL),
2744 inlining_kind_(inlining_kind), 2513 inlining_kind_(inlining_kind),
2745 function_return_(NULL), 2514 function_return_(NULL),
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
3172 2941
3173 #ifdef DEBUG 2942 #ifdef DEBUG
3174 // Do a full verify after building the graph and computing dominators. 2943 // Do a full verify after building the graph and computing dominators.
3175 Verify(true); 2944 Verify(true);
3176 #endif 2945 #endif
3177 2946
3178 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) { 2947 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
3179 Run<HEnvironmentLivenessAnalysisPhase>(); 2948 Run<HEnvironmentLivenessAnalysisPhase>();
3180 } 2949 }
3181 2950
3182 PropagateDeoptimizingMark(); 2951 Run<HPropagateDeoptimizingMarkPhase>();
3183 if (!CheckConstPhiUses()) { 2952 if (!CheckConstPhiUses()) {
3184 *bailout_reason = SmartArrayPointer<char>(StrDup( 2953 *bailout_reason = SmartArrayPointer<char>(StrDup(
3185 "Unsupported phi use of const variable")); 2954 "Unsupported phi use of const variable"));
3186 return false; 2955 return false;
3187 } 2956 }
3188 Run<HRedundantPhiEliminationPhase>(); 2957 Run<HRedundantPhiEliminationPhase>();
3189 if (!CheckArgumentsPhiUses()) { 2958 if (!CheckArgumentsPhiUses()) {
3190 *bailout_reason = SmartArrayPointer<char>(StrDup( 2959 *bailout_reason = SmartArrayPointer<char>(StrDup(
3191 "Unsupported phi use of arguments")); 2960 "Unsupported phi use of arguments"));
3192 return false; 2961 return false;
3193 } 2962 }
3194 2963
3195 // Remove dead code and phis 2964 // Remove dead code and phis
3196 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); 2965 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
3197 CollectPhis(); 2966 CollectPhis();
3198 2967
3199 if (has_osr()) osr()->FinishOsrValues(); 2968 if (has_osr()) osr()->FinishOsrValues();
3200 2969
3201 Run<HInferRepresentationPhase>(); 2970 Run<HInferRepresentationPhase>();
3202 2971
3203 // Remove HSimulate instructions that have turned out not to be needed 2972 // Remove HSimulate instructions that have turned out not to be needed
3204 // after all by folding them into the following HSimulate. 2973 // after all by folding them into the following HSimulate.
3205 // This must happen after inferring representations. 2974 // This must happen after inferring representations.
3206 MergeRemovableSimulates(); 2975 Run<HMergeRemovableSimulatesPhase>();
3207 2976
3208 MarkDeoptimizeOnUndefined(); 2977 MarkDeoptimizeOnUndefined();
3209 Run<HRepresentationChangesPhase>(); 2978 Run<HRepresentationChangesPhase>();
3210 2979
3211 Run<HInferTypesPhase>(); 2980 Run<HInferTypesPhase>();
3212 2981
3213 // Must be performed before canonicalization to ensure that Canonicalize 2982 // Must be performed before canonicalization to ensure that Canonicalize
3214 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with 2983 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
3215 // zero. 2984 // zero.
3216 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>(); 2985 if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>();
3217 2986
3218 if (FLAG_use_canonicalizing) Canonicalize(); 2987 if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
3219 2988
3220 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>(); 2989 if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
3221 2990
3222 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); 2991 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
3223 2992
3224 if (FLAG_use_range) Run<HRangeAnalysisPhase>(); 2993 if (FLAG_use_range) Run<HRangeAnalysisPhase>();
3225 2994
3226 ComputeMinusZeroChecks(); 2995 Run<HComputeMinusZeroChecksPhase>();
3227 2996
3228 // Eliminate redundant stack checks on backwards branches. 2997 // Eliminate redundant stack checks on backwards branches.
3229 Run<HStackCheckEliminationPhase>(); 2998 Run<HStackCheckEliminationPhase>();
3230 2999
3231 if (FLAG_idefs) SetupInformativeDefinitions(); 3000 if (FLAG_idefs) SetupInformativeDefinitions();
3232 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) { 3001 if (FLAG_array_bounds_checks_elimination && !FLAG_idefs) {
3233 Run<HBoundsCheckEliminationPhase>(); 3002 Run<HBoundsCheckEliminationPhase>();
3234 } 3003 }
3235 if (FLAG_array_index_dehoisting) DehoistSimpleArrayIndexComputations(); 3004 if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
3236 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>(); 3005 if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
3237 3006
3238 RestoreActualValues(); 3007 RestoreActualValues();
3239 3008
3240 return true; 3009 return true;
3241 } 3010 }
3242 3011
3243 3012
3244 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) { 3013 void HGraph::SetupInformativeDefinitionsInBlock(HBasicBlock* block) {
3245 for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) { 3014 for (int phi_index = 0; phi_index < block->phis()->length(); phi_index++) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3278 } 3047 }
3279 } 3048 }
3280 3049
3281 3050
3282 void HGraph::SetupInformativeDefinitions() { 3051 void HGraph::SetupInformativeDefinitions() {
3283 HPhase phase("H_Setup informative definitions", this); 3052 HPhase phase("H_Setup informative definitions", this);
3284 SetupInformativeDefinitionsRecursively(entry_block()); 3053 SetupInformativeDefinitionsRecursively(entry_block());
3285 } 3054 }
3286 3055
3287 3056
3288 static void DehoistArrayIndex(ArrayInstructionInterface* array_operation) {
3289 HValue* index = array_operation->GetKey()->ActualValue();
3290 if (!index->representation().IsSmiOrInteger32()) return;
3291
3292 HConstant* constant;
3293 HValue* subexpression;
3294 int32_t sign;
3295 if (index->IsAdd()) {
3296 sign = 1;
3297 HAdd* add = HAdd::cast(index);
3298 if (add->left()->IsConstant()) {
3299 subexpression = add->right();
3300 constant = HConstant::cast(add->left());
3301 } else if (add->right()->IsConstant()) {
3302 subexpression = add->left();
3303 constant = HConstant::cast(add->right());
3304 } else {
3305 return;
3306 }
3307 } else if (index->IsSub()) {
3308 sign = -1;
3309 HSub* sub = HSub::cast(index);
3310 if (sub->left()->IsConstant()) {
3311 subexpression = sub->right();
3312 constant = HConstant::cast(sub->left());
3313 } else if (sub->right()->IsConstant()) {
3314 subexpression = sub->left();
3315 constant = HConstant::cast(sub->right());
3316 } else {
3317 return;
3318 }
3319 } else {
3320 return;
3321 }
3322
3323 if (!constant->HasInteger32Value()) return;
3324 int32_t value = constant->Integer32Value() * sign;
3325 // We limit offset values to 30 bits because we want to avoid the risk of
3326 // overflows when the offset is added to the object header size.
3327 if (value >= 1 << 30 || value < 0) return;
3328 array_operation->SetKey(subexpression);
3329 if (index->HasNoUses()) {
3330 index->DeleteAndReplaceWith(NULL);
3331 }
3332 ASSERT(value >= 0);
3333 array_operation->SetIndexOffset(static_cast<uint32_t>(value));
3334 array_operation->SetDehoisted(true);
3335 }
3336
3337
3338 void HGraph::DehoistSimpleArrayIndexComputations() {
3339 HPhase phase("H_Dehoist index computations", this);
3340 for (int i = 0; i < blocks()->length(); ++i) {
3341 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
3342 HInstruction* instr = it.Current();
3343 ArrayInstructionInterface* array_instruction = NULL;
3344 if (instr->IsLoadKeyed()) {
3345 HLoadKeyed* op = HLoadKeyed::cast(instr);
3346 array_instruction = static_cast<ArrayInstructionInterface*>(op);
3347 } else if (instr->IsStoreKeyed()) {
3348 HStoreKeyed* op = HStoreKeyed::cast(instr);
3349 array_instruction = static_cast<ArrayInstructionInterface*>(op);
3350 } else {
3351 continue;
3352 }
3353 DehoistArrayIndex(array_instruction);
3354 }
3355 }
3356 }
3357
3358
3359 void HGraph::RestoreActualValues() { 3057 void HGraph::RestoreActualValues() {
3360 HPhase phase("H_Restore actual values", this); 3058 HPhase phase("H_Restore actual values", this);
3361 3059
3362 for (int block_index = 0; block_index < blocks()->length(); block_index++) { 3060 for (int block_index = 0; block_index < blocks()->length(); block_index++) {
3363 HBasicBlock* block = blocks()->at(block_index); 3061 HBasicBlock* block = blocks()->at(block_index);
3364 3062
3365 #ifdef DEBUG 3063 #ifdef DEBUG
3366 for (int i = 0; i < block->phis()->length(); i++) { 3064 for (int i = 0; i < block->phis()->length(); i++) {
3367 HPhi* phi = block->phis()->at(i); 3065 HPhi* phi = block->phis()->at(i);
3368 ASSERT(phi->ActualValue() == phi); 3066 ASSERT(phi->ActualValue() == phi);
(...skipping 1539 matching lines...) Expand 10 before | Expand all | Expand 10 after
4908 HValue* context = environment()->LookupContext(); 4606 HValue* context = environment()->LookupContext();
4909 return new(zone()) HStoreNamedGeneric( 4607 return new(zone()) HStoreNamedGeneric(
4910 context, 4608 context,
4911 object, 4609 object,
4912 name, 4610 name,
4913 value, 4611 value,
4914 function_strict_mode_flag()); 4612 function_strict_mode_flag());
4915 } 4613 }
4916 4614
4917 4615
4918 HInstruction* HOptimizedGraphBuilder::BuildCallSetter(
4919 HValue* object,
4920 HValue* value,
4921 Handle<Map> map,
4922 Handle<JSFunction> setter,
4923 Handle<JSObject> holder) {
4924 AddCheckConstantFunction(holder, object, map);
4925 Add<HPushArgument>(object);
4926 Add<HPushArgument>(value);
4927 return new(zone()) HCallConstantFunction(setter, 2);
4928 }
4929
4930
4931 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( 4616 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic(
4932 HValue* object, 4617 HValue* object,
4933 Handle<String> name, 4618 Handle<String> name,
4934 HValue* value, 4619 HValue* value,
4935 Handle<Map> map) { 4620 Handle<Map> map) {
4936 // Handle a store to a known field. 4621 // Handle a store to a known field.
4937 LookupResult lookup(isolate()); 4622 LookupResult lookup(isolate());
4938 if (ComputeLoadStoreField(map, name, &lookup, true)) { 4623 if (ComputeLoadStoreField(map, name, &lookup, true)) {
4939 AddCheckMapsWithTransitions(object, map); 4624 AddCheckMapsWithTransitions(object, map);
4940 return BuildStoreNamedField(object, name, value, map, &lookup); 4625 return BuildStoreNamedField(object, name, value, map, &lookup);
(...skipping 1176 matching lines...) Expand 10 before | Expand all | Expand 10 after
6117 instr = BuildMonomorphicElementAccess( 5802 instr = BuildMonomorphicElementAccess(
6118 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); 5803 obj, key, val, NULL, map, is_store, expr->GetStoreMode());
6119 } 5804 }
6120 } else if (expr->GetReceiverTypes() != NULL && 5805 } else if (expr->GetReceiverTypes() != NULL &&
6121 !expr->GetReceiverTypes()->is_empty()) { 5806 !expr->GetReceiverTypes()->is_empty()) {
6122 return HandlePolymorphicElementAccess( 5807 return HandlePolymorphicElementAccess(
6123 obj, key, val, expr, ast_id, position, is_store, 5808 obj, key, val, expr, ast_id, position, is_store,
6124 expr->GetStoreMode(), has_side_effects); 5809 expr->GetStoreMode(), has_side_effects);
6125 } else { 5810 } else {
6126 if (is_store) { 5811 if (is_store) {
5812 if (expr->IsAssignment() && expr->AsAssignment()->IsUninitialized()) {
5813 AddSoftDeoptimize();
5814 }
6127 instr = BuildStoreKeyedGeneric(obj, key, val); 5815 instr = BuildStoreKeyedGeneric(obj, key, val);
6128 } else { 5816 } else {
5817 if (expr->AsProperty()->IsUninitialized()) {
5818 AddSoftDeoptimize();
5819 }
6129 instr = BuildLoadKeyedGeneric(obj, key); 5820 instr = BuildLoadKeyedGeneric(obj, key);
6130 } 5821 }
6131 AddInstruction(instr); 5822 AddInstruction(instr);
6132 } 5823 }
6133 if (position != RelocInfo::kNoPosition) instr->set_position(position); 5824 if (position != RelocInfo::kNoPosition) instr->set_position(position);
6134 *has_side_effects = instr->HasObservableSideEffects(); 5825 *has_side_effects = instr->HasObservableSideEffects();
6135 return instr; 5826 return instr;
6136 } 5827 }
6137 5828
6138 5829
(...skipping 1282 matching lines...) Expand 10 before | Expand all | Expand 10 after
7421 return; 7112 return;
7422 7113
7423 } else { 7114 } else {
7424 HValue* context = environment()->LookupContext(); 7115 HValue* context = environment()->LookupContext();
7425 call = PreProcessCall( 7116 call = PreProcessCall(
7426 new(zone()) HCallNamed(context, name, argument_count)); 7117 new(zone()) HCallNamed(context, name, argument_count));
7427 } 7118 }
7428 7119
7429 } else { 7120 } else {
7430 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 7121 VariableProxy* proxy = expr->expression()->AsVariableProxy();
7431 bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
7432
7433 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { 7122 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
7434 return Bailout("possible direct call to eval"); 7123 return Bailout("possible direct call to eval");
7435 } 7124 }
7436 7125
7126 bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
7437 if (global_call) { 7127 if (global_call) {
7438 Variable* var = proxy->var(); 7128 Variable* var = proxy->var();
7439 bool known_global_function = false; 7129 bool known_global_function = false;
7440 // If there is a global property cell for the name at compile time and 7130 // If there is a global property cell for the name at compile time and
7441 // access check is not enabled we assume that the function will not change 7131 // access check is not enabled we assume that the function will not change
7442 // and generate optimized code for calling the function. 7132 // and generate optimized code for calling the function.
7443 LookupResult lookup(isolate()); 7133 LookupResult lookup(isolate());
7444 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 7134 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
7445 if (type == kUseCell && 7135 if (type == kUseCell &&
7446 !current_info()->global_object()->IsAccessCheckNeeded()) { 7136 !current_info()->global_object()->IsAccessCheckNeeded()) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
7549 7239
7550 call->set_position(expr->position()); 7240 call->set_position(expr->position());
7551 return ast_context()->ReturnInstruction(call, expr->id()); 7241 return ast_context()->ReturnInstruction(call, expr->id());
7552 } 7242 }
7553 7243
7554 7244
7555 // Checks whether allocation using the given constructor can be inlined. 7245 // Checks whether allocation using the given constructor can be inlined.
7556 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { 7246 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
7557 return constructor->has_initial_map() && 7247 return constructor->has_initial_map() &&
7558 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && 7248 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
7559 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; 7249 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
7250 constructor->initial_map()->InitialPropertiesLength() == 0;
7560 } 7251 }
7561 7252
7562 7253
7563 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { 7254 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
7564 ASSERT(!HasStackOverflow()); 7255 ASSERT(!HasStackOverflow());
7565 ASSERT(current_block() != NULL); 7256 ASSERT(current_block() != NULL);
7566 ASSERT(current_block()->HasPredecessor()); 7257 ASSERT(current_block()->HasPredecessor());
7567 int argument_count = expr->arguments()->length() + 1; // Plus constructor. 7258 int argument_count = expr->arguments()->length() + 1; // Plus constructor.
7568 HValue* context = environment()->LookupContext(); 7259 HValue* context = environment()->LookupContext();
7260 Factory* factory = isolate()->factory();
7569 7261
7570 if (FLAG_inline_construct && 7262 if (FLAG_inline_construct &&
7571 expr->IsMonomorphic() && 7263 expr->IsMonomorphic() &&
7572 IsAllocationInlineable(expr->target())) { 7264 IsAllocationInlineable(expr->target())) {
7573 // The constructor function is on the stack in the unoptimized code 7265 // The constructor function is on the stack in the unoptimized code
7574 // during evaluation of the arguments. 7266 // during evaluation of the arguments.
7575 CHECK_ALIVE(VisitForValue(expr->expression())); 7267 CHECK_ALIVE(VisitForValue(expr->expression()));
7576 HValue* function = Top(); 7268 HValue* function = Top();
7577 CHECK_ALIVE(VisitExpressions(expr->arguments())); 7269 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7578 Handle<JSFunction> constructor = expr->target(); 7270 Handle<JSFunction> constructor = expr->target();
7579 HValue* check = Add<HCheckFunction>(function, constructor); 7271 HValue* check = Add<HCheckFunction>(function, constructor);
7580 7272
7581 // Force completion of inobject slack tracking before generating 7273 // Force completion of inobject slack tracking before generating
7582 // allocation code to finalize instance size. 7274 // allocation code to finalize instance size.
7583 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { 7275 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) {
7584 constructor->shared()->CompleteInobjectSlackTracking(); 7276 constructor->shared()->CompleteInobjectSlackTracking();
7585 } 7277 }
7586 7278
7587 // Replace the constructor function with a newly allocated receiver. 7279 // Calculate instance size from initial map of constructor.
7588 HInstruction* receiver = Add<HAllocateObject>(context, constructor); 7280 ASSERT(constructor->has_initial_map());
7589 // Index of the receiver from the top of the expression stack. 7281 Handle<Map> initial_map(constructor->initial_map());
7282 int instance_size = initial_map->instance_size();
7283 ASSERT(initial_map->InitialPropertiesLength() == 0);
7284
7285 // Allocate an instance of the implicit receiver object.
7286 HValue* size_in_bytes = Add<HConstant>(instance_size);
7287 HAllocate::Flags flags = HAllocate::DefaultFlags();
7288 if (FLAG_pretenuring_call_new &&
7289 isolate()->heap()->ShouldGloballyPretenure()) {
7290 flags = static_cast<HAllocate::Flags>(
7291 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE);
7292 }
7293 HAllocate* receiver =
7294 Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags);
7295 receiver->set_known_initial_map(initial_map);
7296
7297 // Load the initial map from the constructor.
7298 HValue* constructor_value = Add<HConstant>(constructor);
7299 HValue* initial_map_value =
7300 AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset(
7301 JSFunction::kPrototypeOrInitialMapOffset));
7302
7303 // Initialize map and fields of the newly allocated object.
7304 { NoObservableSideEffectsScope no_effects(this);
7305 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
7306 AddStore(receiver,
7307 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset),
7308 initial_map_value);
7309 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
7310 AddStore(receiver,
7311 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset),
7312 empty_fixed_array);
7313 AddStore(receiver,
7314 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset),
7315 empty_fixed_array);
7316 if (initial_map->inobject_properties() != 0) {
7317 HConstant* undefined = graph()->GetConstantUndefined();
7318 for (int i = 0; i < initial_map->inobject_properties(); i++) {
7319 int property_offset = JSObject::kHeaderSize + i * kPointerSize;
7320 AddStore(receiver,
7321 HObjectAccess::ForJSObjectOffset(property_offset),
7322 undefined);
7323 }
7324 }
7325 }
7326
7327 // Replace the constructor function with a newly allocated receiver using
7328 // the index of the receiver from the top of the expression stack.
7590 const int receiver_index = argument_count - 1; 7329 const int receiver_index = argument_count - 1;
7591 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); 7330 ASSERT(environment()->ExpressionStackAt(receiver_index) == function);
7592 environment()->SetExpressionStackAt(receiver_index, receiver); 7331 environment()->SetExpressionStackAt(receiver_index, receiver);
7593 7332
7594 if (TryInlineConstruct(expr, receiver)) return; 7333 if (TryInlineConstruct(expr, receiver)) return;
7595 7334
7596 // TODO(mstarzinger): For now we remove the previous HAllocateObject and 7335 // TODO(mstarzinger): For now we remove the previous HAllocate and all
7597 // add HPushArgument for the arguments in case inlining failed. What we 7336 // corresponding instructions and instead add HPushArgument for the
7598 // actually should do is emit HInvokeFunction on the constructor instead 7337 // arguments in case inlining failed. What we actually should do is for
7599 // of using HCallNew as a fallback. 7338 // inlining to try to build a subgraph without mutating the parent graph.
7339 HInstruction* instr = current_block()->last();
7340 while (instr != initial_map_value) {
7341 HInstruction* prev_instr = instr->previous();
7342 instr->DeleteAndReplaceWith(NULL);
7343 instr = prev_instr;
7344 }
7345 initial_map_value->DeleteAndReplaceWith(NULL);
7600 receiver->DeleteAndReplaceWith(NULL); 7346 receiver->DeleteAndReplaceWith(NULL);
7601 check->DeleteAndReplaceWith(NULL); 7347 check->DeleteAndReplaceWith(NULL);
7602 environment()->SetExpressionStackAt(receiver_index, function); 7348 environment()->SetExpressionStackAt(receiver_index, function);
7603 HInstruction* call = PreProcessCall( 7349 HInstruction* call = PreProcessCall(
7604 new(zone()) HCallNew(context, function, argument_count)); 7350 new(zone()) HCallNew(context, function, argument_count));
7605 call->set_position(expr->position()); 7351 call->set_position(expr->position());
7606 return ast_context()->ReturnInstruction(call, expr->id()); 7352 return ast_context()->ReturnInstruction(call, expr->id());
7607 } else { 7353 } else {
7608 // The constructor function is both an operand to the instruction and an 7354 // The constructor function is both an operand to the instruction and an
7609 // argument to the construct call. 7355 // argument to the construct call.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
7647 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 7393 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
7648 ASSERT(!HasStackOverflow()); 7394 ASSERT(!HasStackOverflow());
7649 ASSERT(current_block() != NULL); 7395 ASSERT(current_block() != NULL);
7650 ASSERT(current_block()->HasPredecessor()); 7396 ASSERT(current_block()->HasPredecessor());
7651 if (expr->is_jsruntime()) { 7397 if (expr->is_jsruntime()) {
7652 return Bailout("call to a JavaScript runtime function"); 7398 return Bailout("call to a JavaScript runtime function");
7653 } 7399 }
7654 7400
7655 const Runtime::Function* function = expr->function(); 7401 const Runtime::Function* function = expr->function();
7656 ASSERT(function != NULL); 7402 ASSERT(function != NULL);
7403
7404 if (static_cast<int>(function->function_id)
7405 == static_cast<int>(Runtime::kNeverOptimize)
7406 && expr->arguments()->length() == 0) {
7407 // %NeverOptimize() without arguments marks the caller as never optimize.
7408 return Bailout("function marked itself as never optimize");
7409 }
7410
7657 if (function->intrinsic_type == Runtime::INLINE) { 7411 if (function->intrinsic_type == Runtime::INLINE) {
7658 ASSERT(expr->name()->length() > 0); 7412 ASSERT(expr->name()->length() > 0);
7659 ASSERT(expr->name()->Get(0) == '_'); 7413 ASSERT(expr->name()->Get(0) == '_');
7660 // Call to an inline function. 7414 // Call to an inline function.
7661 int lookup_index = static_cast<int>(function->function_id) - 7415 int lookup_index = static_cast<int>(function->function_id) -
7662 static_cast<int>(Runtime::kFirstInlineFunction); 7416 static_cast<int>(Runtime::kFirstInlineFunction);
7663 ASSERT(lookup_index >= 0); 7417 ASSERT(lookup_index >= 0);
7664 ASSERT(static_cast<size_t>(lookup_index) < 7418 ASSERT(static_cast<size_t>(lookup_index) <
7665 ARRAY_SIZE(kInlineFunctionGenerators)); 7419 ARRAY_SIZE(kInlineFunctionGenerators));
7666 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 7420 InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
7750 HValue* value = Pop(); 7504 HValue* value = Pop();
7751 HValue* context = environment()->LookupContext(); 7505 HValue* context = environment()->LookupContext();
7752 HInstruction* instr = new(zone()) HTypeof(context, value); 7506 HInstruction* instr = new(zone()) HTypeof(context, value);
7753 return ast_context()->ReturnInstruction(instr, expr->id()); 7507 return ast_context()->ReturnInstruction(instr, expr->id());
7754 } 7508 }
7755 7509
7756 7510
7757 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { 7511 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
7758 CHECK_ALIVE(VisitForValue(expr->expression())); 7512 CHECK_ALIVE(VisitForValue(expr->expression()));
7759 HValue* value = Pop(); 7513 HValue* value = Pop();
7760 Handle<Type> operand_type = expr->expression()->lower_type(); 7514 Handle<Type> operand_type = expr->expression()->bounds().lower;
7761 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB); 7515 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::SUB);
7762 return ast_context()->ReturnInstruction(instr, expr->id()); 7516 return ast_context()->ReturnInstruction(instr, expr->id());
7763 } 7517 }
7764 7518
7765 7519
7766 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { 7520 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
7767 CHECK_ALIVE(VisitForValue(expr->expression())); 7521 CHECK_ALIVE(VisitForValue(expr->expression()));
7768 HValue* value = Pop(); 7522 HValue* value = Pop();
7769 Handle<Type> operand_type = expr->expression()->lower_type(); 7523 Handle<Type> operand_type = expr->expression()->bounds().lower;
7770 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT); 7524 HInstruction* instr = BuildUnaryMathOp(value, operand_type, Token::BIT_NOT);
7771 return ast_context()->ReturnInstruction(instr, expr->id()); 7525 return ast_context()->ReturnInstruction(instr, expr->id());
7772 } 7526 }
7773 7527
7774 7528
7775 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { 7529 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
7776 if (ast_context()->IsTest()) { 7530 if (ast_context()->IsTest()) {
7777 TestContext* context = TestContext::cast(ast_context()); 7531 TestContext* context = TestContext::cast(ast_context());
7778 VisitForControl(expr->expression(), 7532 VisitForControl(expr->expression(),
7779 context->if_false(), 7533 context->if_false(),
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
8095 } 7849 }
8096 return true; 7850 return true;
8097 } 7851 }
8098 7852
8099 7853
8100 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( 7854 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
8101 BinaryOperation* expr, 7855 BinaryOperation* expr,
8102 HValue* left, 7856 HValue* left,
8103 HValue* right) { 7857 HValue* right) {
8104 HValue* context = environment()->LookupContext(); 7858 HValue* context = environment()->LookupContext();
8105 Handle<Type> left_type = expr->left()->lower_type(); 7859 Handle<Type> left_type = expr->left()->bounds().lower;
8106 Handle<Type> right_type = expr->right()->lower_type(); 7860 Handle<Type> right_type = expr->right()->bounds().lower;
8107 Handle<Type> result_type = expr->lower_type(); 7861 Handle<Type> result_type = expr->bounds().lower;
8108 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); 7862 Maybe<int> fixed_right_arg = expr->fixed_right_arg();
8109 Representation left_rep = Representation::FromType(left_type); 7863 Representation left_rep = Representation::FromType(left_type);
8110 Representation right_rep = Representation::FromType(right_type); 7864 Representation right_rep = Representation::FromType(right_type);
8111 Representation result_rep = Representation::FromType(result_type); 7865 Representation result_rep = Representation::FromType(result_type);
8112 7866
8113 if (left_type->Is(Type::None())) { 7867 if (left_type->Is(Type::None())) {
8114 AddSoftDeoptimize(); 7868 AddSoftDeoptimize();
8115 // TODO(rossberg): we should be able to get rid of non-continuous defaults. 7869 // TODO(rossberg): we should be able to get rid of non-continuous defaults.
8116 left_type = handle(Type::Any(), isolate()); 7870 left_type = handle(Type::Any(), isolate());
8117 } 7871 }
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
8419 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 8173 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
8420 HValue* value = Pop(); 8174 HValue* value = Pop();
8421 Literal* literal = expr->right()->AsLiteral(); 8175 Literal* literal = expr->right()->AsLiteral();
8422 Handle<String> rhs = Handle<String>::cast(literal->value()); 8176 Handle<String> rhs = Handle<String>::cast(literal->value());
8423 HClassOfTestAndBranch* instr = 8177 HClassOfTestAndBranch* instr =
8424 new(zone()) HClassOfTestAndBranch(value, rhs); 8178 new(zone()) HClassOfTestAndBranch(value, rhs);
8425 instr->set_position(expr->position()); 8179 instr->set_position(expr->position());
8426 return ast_context()->ReturnControl(instr, expr->id()); 8180 return ast_context()->ReturnControl(instr, expr->id());
8427 } 8181 }
8428 8182
8429 Handle<Type> left_type = expr->left()->lower_type(); 8183 Handle<Type> left_type = expr->left()->bounds().lower;
8430 Handle<Type> right_type = expr->right()->lower_type(); 8184 Handle<Type> right_type = expr->right()->bounds().lower;
8431 Handle<Type> combined_type = expr->combined_type(); 8185 Handle<Type> combined_type = expr->combined_type();
8432 Representation combined_rep = Representation::FromType(combined_type); 8186 Representation combined_rep = Representation::FromType(combined_type);
8433 Representation left_rep = Representation::FromType(left_type); 8187 Representation left_rep = Representation::FromType(left_type);
8434 Representation right_rep = Representation::FromType(right_type); 8188 Representation right_rep = Representation::FromType(right_type);
8435 8189
8436 CHECK_ALIVE(VisitForValue(expr->left())); 8190 CHECK_ALIVE(VisitForValue(expr->left()));
8437 CHECK_ALIVE(VisitForValue(expr->right())); 8191 CHECK_ALIVE(VisitForValue(expr->right()));
8438 8192
8439 HValue* context = environment()->LookupContext(); 8193 HValue* context = environment()->LookupContext();
8440 HValue* right = Pop(); 8194 HValue* right = Pop();
(...skipping 1801 matching lines...) Expand 10 before | Expand all | Expand 10 after
10242 if (ShouldProduceTraceOutput()) { 9996 if (ShouldProduceTraceOutput()) {
10243 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 9997 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
10244 } 9998 }
10245 9999
10246 #ifdef DEBUG 10000 #ifdef DEBUG
10247 graph_->Verify(false); // No full verify. 10001 graph_->Verify(false); // No full verify.
10248 #endif 10002 #endif
10249 } 10003 }
10250 10004
10251 } } // namespace v8::internal 10005 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-canonicalize.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698