jkummerow@chromium.org | 05ed9dd | 2012-01-23 14:42:48 +0000 | [diff] [blame] | 1 | // Copyright 2012 the V8 project authors. All rights reserved. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2 | // Redistribution and use in source and binary forms, with or without |
| 3 | // modification, are permitted provided that the following conditions are |
| 4 | // met: |
| 5 | // |
| 6 | // * Redistributions of source code must retain the above copyright |
| 7 | // notice, this list of conditions and the following disclaimer. |
| 8 | // * Redistributions in binary form must reproduce the above |
| 9 | // copyright notice, this list of conditions and the following |
| 10 | // disclaimer in the documentation and/or other materials provided |
| 11 | // with the distribution. |
| 12 | // * Neither the name of Google Inc. nor the names of its |
| 13 | // contributors may be used to endorse or promote products derived |
| 14 | // from this software without specific prior written permission. |
| 15 | // |
| 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | |
| 28 | #ifndef V8_HYDROGEN_H_ |
| 29 | #define V8_HYDROGEN_H_ |
| 30 | |
| 31 | #include "v8.h" |
| 32 | |
machenbach@chromium.org | 8e36b5b | 2013-09-26 07:36:30 +0000 | [diff] [blame] | 33 | #include "accessors.h" |
lrn@chromium.org | 1c09276 | 2011-05-09 09:42:16 +0000 | [diff] [blame] | 34 | #include "allocation.h" |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 35 | #include "ast.h" |
| 36 | #include "compiler.h" |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 37 | #include "hydrogen-instructions.h" |
| 38 | #include "zone.h" |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 39 | #include "scopes.h" |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 40 | |
| 41 | namespace v8 { |
| 42 | namespace internal { |
| 43 | |
| 44 | // Forward declarations. |
fschneider@chromium.org | fb144a0 | 2011-05-04 12:43:48 +0000 | [diff] [blame] | 45 | class BitVector; |
jkummerow@chromium.org | 28faa98 | 2012-04-13 09:58:30 +0000 | [diff] [blame] | 46 | class FunctionState; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 47 | class HEnvironment; |
| 48 | class HGraph; |
| 49 | class HLoopInformation; |
machenbach@chromium.org | c1789ee | 2013-07-05 07:09:57 +0000 | [diff] [blame] | 50 | class HOsrBuilder; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 51 | class HTracer; |
| 52 | class LAllocator; |
jkummerow@chromium.org | 28583c9 | 2012-07-16 11:31:55 +0000 | [diff] [blame] | 53 | class LChunk; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 54 | class LiveRange; |
| 55 | |
| 56 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 57 | class HBasicBlock V8_FINAL : public ZoneObject { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 58 | public: |
| 59 | explicit HBasicBlock(HGraph* graph); |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 60 | ~HBasicBlock() { } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 61 | |
| 62 | // Simple accessors. |
| 63 | int block_id() const { return block_id_; } |
| 64 | void set_block_id(int id) { block_id_ = id; } |
| 65 | HGraph* graph() const { return graph_; } |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 66 | Isolate* isolate() const; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 67 | const ZoneList<HPhi*>* phis() const { return &phis_; } |
| 68 | HInstruction* first() const { return first_; } |
kmillikin@chromium.org | 49edbdf | 2011-02-16 12:32:18 +0000 | [diff] [blame] | 69 | HInstruction* last() const { return last_; } |
| 70 | void set_last(HInstruction* instr) { last_ = instr; } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 71 | HControlInstruction* end() const { return end_; } |
| 72 | HLoopInformation* loop_information() const { return loop_information_; } |
jkummerow@chromium.org | fb732b1 | 2013-07-26 10:27:09 +0000 | [diff] [blame] | 73 | HLoopInformation* current_loop() const { |
| 74 | return IsLoopHeader() ? loop_information() |
| 75 | : (parent_loop_header() != NULL |
| 76 | ? parent_loop_header()->loop_information() : NULL); |
| 77 | } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 78 | const ZoneList<HBasicBlock*>* predecessors() const { return &predecessors_; } |
| 79 | bool HasPredecessor() const { return predecessors_.length() > 0; } |
| 80 | const ZoneList<HBasicBlock*>* dominated_blocks() const { |
| 81 | return &dominated_blocks_; |
| 82 | } |
| 83 | const ZoneList<int>* deleted_phis() const { |
| 84 | return &deleted_phis_; |
| 85 | } |
| 86 | void RecordDeletedPhi(int merge_index) { |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 87 | deleted_phis_.Add(merge_index, zone()); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 88 | } |
| 89 | HBasicBlock* dominator() const { return dominator_; } |
| 90 | HEnvironment* last_environment() const { return last_environment_; } |
| 91 | int argument_count() const { return argument_count_; } |
| 92 | void set_argument_count(int count) { argument_count_ = count; } |
| 93 | int first_instruction_index() const { return first_instruction_index_; } |
| 94 | void set_first_instruction_index(int index) { |
| 95 | first_instruction_index_ = index; |
| 96 | } |
| 97 | int last_instruction_index() const { return last_instruction_index_; } |
| 98 | void set_last_instruction_index(int index) { |
| 99 | last_instruction_index_ = index; |
| 100 | } |
hpayer@chromium.org | 7c3372b | 2013-02-13 17:26:04 +0000 | [diff] [blame] | 101 | bool is_osr_entry() { return is_osr_entry_; } |
| 102 | void set_osr_entry() { is_osr_entry_ = true; } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 103 | |
| 104 | void AttachLoopInformation(); |
| 105 | void DetachLoopInformation(); |
| 106 | bool IsLoopHeader() const { return loop_information() != NULL; } |
| 107 | bool IsStartBlock() const { return block_id() == 0; } |
| 108 | void PostProcessLoopHeader(IterationStatement* stmt); |
| 109 | |
| 110 | bool IsFinished() const { return end_ != NULL; } |
| 111 | void AddPhi(HPhi* phi); |
| 112 | void RemovePhi(HPhi* phi); |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 113 | void AddInstruction(HInstruction* instr, int position); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 114 | bool Dominates(HBasicBlock* other) const; |
kmillikin@chromium.org | 83e1682 | 2011-09-13 08:21:47 +0000 | [diff] [blame] | 115 | int LoopNestingDepth() const; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 116 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 117 | void SetInitialEnvironment(HEnvironment* env); |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 118 | void ClearEnvironment() { |
| 119 | ASSERT(IsFinished()); |
| 120 | ASSERT(end()->SuccessorCount() == 0); |
| 121 | last_environment_ = NULL; |
| 122 | } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 123 | bool HasEnvironment() const { return last_environment_ != NULL; } |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 124 | void UpdateEnvironment(HEnvironment* env); |
sgjesse@chromium.org | 496c03a | 2011-02-14 12:05:43 +0000 | [diff] [blame] | 125 | HBasicBlock* parent_loop_header() const { return parent_loop_header_; } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 126 | |
| 127 | void set_parent_loop_header(HBasicBlock* block) { |
sgjesse@chromium.org | 496c03a | 2011-02-14 12:05:43 +0000 | [diff] [blame] | 128 | ASSERT(parent_loop_header_ == NULL); |
| 129 | parent_loop_header_ = block; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 130 | } |
| 131 | |
sgjesse@chromium.org | 496c03a | 2011-02-14 12:05:43 +0000 | [diff] [blame] | 132 | bool HasParentLoopHeader() const { return parent_loop_header_ != NULL; } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 133 | |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 134 | void SetJoinId(BailoutId ast_id); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 135 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 136 | int PredecessorIndexOf(HBasicBlock* predecessor) const; |
danno@chromium.org | ad75d6f | 2013-08-12 16:57:59 +0000 | [diff] [blame] | 137 | HPhi* AddNewPhi(int merged_index); |
| 138 | HSimulate* AddNewSimulate(BailoutId ast_id, |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 139 | int position, |
danno@chromium.org | ad75d6f | 2013-08-12 16:57:59 +0000 | [diff] [blame] | 140 | RemovableSimulate removable = FIXED_SIMULATE) { |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 141 | HSimulate* instr = CreateSimulate(ast_id, removable); |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 142 | AddInstruction(instr, position); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 143 | return instr; |
yangguo@chromium.org | fb37721 | 2012-11-16 14:43:43 +0000 | [diff] [blame] | 144 | } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 145 | void AssignCommonDominator(HBasicBlock* other); |
yangguo@chromium.org | 78d1ad4 | 2012-02-09 13:53:47 +0000 | [diff] [blame] | 146 | void AssignLoopSuccessorDominators(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 147 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 148 | // If a target block is tagged as an inline function return, all |
| 149 | // predecessors should contain the inlined exit sequence: |
| 150 | // |
| 151 | // LeaveInlined |
| 152 | // Simulate (caller's environment) |
| 153 | // Goto (target block) |
| 154 | bool IsInlineReturnTarget() const { return is_inline_return_target_; } |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 155 | void MarkAsInlineReturnTarget(HBasicBlock* inlined_entry_block) { |
| 156 | is_inline_return_target_ = true; |
| 157 | inlined_entry_block_ = inlined_entry_block; |
| 158 | } |
| 159 | HBasicBlock* inlined_entry_block() { return inlined_entry_block_; } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 160 | |
jkummerow@chromium.org | d8a3a14 | 2013-10-03 12:15:05 +0000 | [diff] [blame] | 161 | bool IsDeoptimizing() const { |
| 162 | return end() != NULL && end()->IsDeoptimize(); |
| 163 | } |
| 164 | |
| 165 | void MarkUnreachable(); |
| 166 | bool IsUnreachable() const { return !is_reachable_; } |
| 167 | bool IsReachable() const { return is_reachable_; } |
svenpanne@chromium.org | 6d786c9 | 2011-06-15 10:58:27 +0000 | [diff] [blame] | 168 | |
yangguo@chromium.org | 78d1ad4 | 2012-02-09 13:53:47 +0000 | [diff] [blame] | 169 | bool IsLoopSuccessorDominator() const { |
| 170 | return dominates_loop_successors_; |
| 171 | } |
| 172 | void MarkAsLoopSuccessorDominator() { |
| 173 | dominates_loop_successors_ = true; |
| 174 | } |
| 175 | |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 176 | inline Zone* zone() const; |
vegorov@chromium.org | 74f333b | 2011-04-06 11:17:46 +0000 | [diff] [blame] | 177 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 178 | #ifdef DEBUG |
| 179 | void Verify(); |
| 180 | #endif |
| 181 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 182 | protected: |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 183 | friend class HGraphBuilder; |
| 184 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 185 | HSimulate* CreateSimulate(BailoutId ast_id, RemovableSimulate removable); |
| 186 | void Finish(HControlInstruction* last, int position); |
| 187 | void FinishExit(HControlInstruction* instruction, int position); |
| 188 | void Goto(HBasicBlock* block, |
| 189 | int position, |
| 190 | FunctionState* state = NULL, |
| 191 | bool add_simulate = true); |
| 192 | void GotoNoSimulate(HBasicBlock* block, int position) { |
| 193 | Goto(block, position, NULL, false); |
| 194 | } |
| 195 | |
| 196 | // Add the inlined function exit sequence, adding an HLeaveInlined |
| 197 | // instruction and updating the bailout environment. |
| 198 | void AddLeaveInlined(HValue* return_value, |
| 199 | FunctionState* state, |
| 200 | int position); |
| 201 | |
| 202 | private: |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 203 | void RegisterPredecessor(HBasicBlock* pred); |
| 204 | void AddDominatedBlock(HBasicBlock* block); |
| 205 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 206 | int block_id_; |
| 207 | HGraph* graph_; |
| 208 | ZoneList<HPhi*> phis_; |
| 209 | HInstruction* first_; |
kmillikin@chromium.org | 49edbdf | 2011-02-16 12:32:18 +0000 | [diff] [blame] | 210 | HInstruction* last_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 211 | HControlInstruction* end_; |
| 212 | HLoopInformation* loop_information_; |
| 213 | ZoneList<HBasicBlock*> predecessors_; |
| 214 | HBasicBlock* dominator_; |
| 215 | ZoneList<HBasicBlock*> dominated_blocks_; |
| 216 | HEnvironment* last_environment_; |
| 217 | // Outgoing parameter count at block exit, set during lithium translation. |
| 218 | int argument_count_; |
| 219 | // Instruction indices into the lithium code stream. |
| 220 | int first_instruction_index_; |
| 221 | int last_instruction_index_; |
| 222 | ZoneList<int> deleted_phis_; |
sgjesse@chromium.org | 496c03a | 2011-02-14 12:05:43 +0000 | [diff] [blame] | 223 | HBasicBlock* parent_loop_header_; |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 224 | // For blocks marked as inline return target: the block with HEnterInlined. |
| 225 | HBasicBlock* inlined_entry_block_; |
| 226 | bool is_inline_return_target_ : 1; |
jkummerow@chromium.org | d8a3a14 | 2013-10-03 12:15:05 +0000 | [diff] [blame] | 227 | bool is_reachable_ : 1; |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 228 | bool dominates_loop_successors_ : 1; |
| 229 | bool is_osr_entry_ : 1; |
yangguo@chromium.org | 78d1ad4 | 2012-02-09 13:53:47 +0000 | [diff] [blame] | 230 | }; |
| 231 | |
| 232 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 233 | class HPredecessorIterator V8_FINAL BASE_EMBEDDED { |
yangguo@chromium.org | 78d1ad4 | 2012-02-09 13:53:47 +0000 | [diff] [blame] | 234 | public: |
| 235 | explicit HPredecessorIterator(HBasicBlock* block) |
| 236 | : predecessor_list_(block->predecessors()), current_(0) { } |
| 237 | |
| 238 | bool Done() { return current_ >= predecessor_list_->length(); } |
| 239 | HBasicBlock* Current() { return predecessor_list_->at(current_); } |
| 240 | void Advance() { current_++; } |
| 241 | |
| 242 | private: |
| 243 | const ZoneList<HBasicBlock*>* predecessor_list_; |
| 244 | int current_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 245 | }; |
| 246 | |
| 247 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 248 | class HInstructionIterator V8_FINAL BASE_EMBEDDED { |
jkummerow@chromium.org | 93a47f4 | 2013-07-02 14:43:41 +0000 | [diff] [blame] | 249 | public: |
danno@chromium.org | 169691d | 2013-07-15 08:01:13 +0000 | [diff] [blame] | 250 | explicit HInstructionIterator(HBasicBlock* block) |
| 251 | : instr_(block->first()) { |
| 252 | next_ = Done() ? NULL : instr_->next(); |
| 253 | } |
jkummerow@chromium.org | 93a47f4 | 2013-07-02 14:43:41 +0000 | [diff] [blame] | 254 | |
danno@chromium.org | 169691d | 2013-07-15 08:01:13 +0000 | [diff] [blame] | 255 | inline bool Done() const { return instr_ == NULL; } |
| 256 | inline HInstruction* Current() { return instr_; } |
| 257 | inline void Advance() { |
| 258 | instr_ = next_; |
| 259 | next_ = Done() ? NULL : instr_->next(); |
| 260 | } |
jkummerow@chromium.org | 93a47f4 | 2013-07-02 14:43:41 +0000 | [diff] [blame] | 261 | |
| 262 | private: |
| 263 | HInstruction* instr_; |
danno@chromium.org | 169691d | 2013-07-15 08:01:13 +0000 | [diff] [blame] | 264 | HInstruction* next_; |
jkummerow@chromium.org | 93a47f4 | 2013-07-02 14:43:41 +0000 | [diff] [blame] | 265 | }; |
| 266 | |
| 267 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 268 | class HLoopInformation V8_FINAL : public ZoneObject { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 269 | public: |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 270 | HLoopInformation(HBasicBlock* loop_header, Zone* zone) |
| 271 | : back_edges_(4, zone), |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 272 | loop_header_(loop_header), |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 273 | blocks_(8, zone), |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 274 | stack_check_(NULL) { |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 275 | blocks_.Add(loop_header, zone); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 276 | } |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 277 | ~HLoopInformation() {} |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 278 | |
| 279 | const ZoneList<HBasicBlock*>* back_edges() const { return &back_edges_; } |
| 280 | const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; } |
| 281 | HBasicBlock* loop_header() const { return loop_header_; } |
| 282 | HBasicBlock* GetLastBackEdge() const; |
| 283 | void RegisterBackEdge(HBasicBlock* block); |
| 284 | |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 285 | HStackCheck* stack_check() const { return stack_check_; } |
| 286 | void set_stack_check(HStackCheck* stack_check) { |
| 287 | stack_check_ = stack_check; |
| 288 | } |
| 289 | |
jkummerow@chromium.org | fb732b1 | 2013-07-26 10:27:09 +0000 | [diff] [blame] | 290 | bool IsNestedInThisLoop(HLoopInformation* other) { |
| 291 | while (other != NULL) { |
| 292 | if (other == this) { |
| 293 | return true; |
| 294 | } |
| 295 | other = other->parent_loop(); |
| 296 | } |
| 297 | return false; |
| 298 | } |
| 299 | HLoopInformation* parent_loop() { |
| 300 | HBasicBlock* parent_header = loop_header()->parent_loop_header(); |
| 301 | return parent_header != NULL ? parent_header->loop_information() : NULL; |
| 302 | } |
| 303 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 304 | private: |
| 305 | void AddBlock(HBasicBlock* block); |
| 306 | |
| 307 | ZoneList<HBasicBlock*> back_edges_; |
| 308 | HBasicBlock* loop_header_; |
| 309 | ZoneList<HBasicBlock*> blocks_; |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 310 | HStackCheck* stack_check_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 311 | }; |
| 312 | |
dslomov@chromium.org | b752d40 | 2013-06-18 11:54:54 +0000 | [diff] [blame] | 313 | |
yangguo@chromium.org | efdb9d7 | 2012-04-26 08:21:05 +0000 | [diff] [blame] | 314 | class BoundsCheckTable; |
jkummerow@chromium.org | fb732b1 | 2013-07-26 10:27:09 +0000 | [diff] [blame] | 315 | class InductionVariableBlocksTable; |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 316 | class HGraph V8_FINAL : public ZoneObject { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 317 | public: |
yangguo@chromium.org | 5a11aaf | 2012-06-20 11:29:00 +0000 | [diff] [blame] | 318 | explicit HGraph(CompilationInfo* info); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 319 | |
ulan@chromium.org | 09d7ab5 | 2013-02-25 15:50:35 +0000 | [diff] [blame] | 320 | Isolate* isolate() const { return isolate_; } |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 321 | Zone* zone() const { return zone_; } |
yangguo@chromium.org | 5a11aaf | 2012-06-20 11:29:00 +0000 | [diff] [blame] | 322 | CompilationInfo* info() const { return info_; } |
vegorov@chromium.org | 74f333b | 2011-04-06 11:17:46 +0000 | [diff] [blame] | 323 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 324 | const ZoneList<HBasicBlock*>* blocks() const { return &blocks_; } |
| 325 | const ZoneList<HPhi*>* phi_list() const { return phi_list_; } |
danno@chromium.org | 4d3fe4e | 2011-03-10 10:14:28 +0000 | [diff] [blame] | 326 | HBasicBlock* entry_block() const { return entry_block_; } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 327 | HEnvironment* start_environment() const { return start_environment_; } |
| 328 | |
machenbach@chromium.org | 3d079fe | 2013-09-25 08:19:55 +0000 | [diff] [blame] | 329 | void FinalizeUniqueness(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 330 | bool ProcessArgumentsObject(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 331 | void OrderBlocks(); |
| 332 | void AssignDominators(); |
mstarzinger@chromium.org | 068ea0a | 2013-01-30 09:39:44 +0000 | [diff] [blame] | 333 | void RestoreActualValues(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 334 | |
| 335 | // Returns false if there are phi-uses of the arguments-object |
| 336 | // which are not supported by the optimizing compiler. |
erik.corry@gmail.com | c3b670f | 2011-10-05 21:44:48 +0000 | [diff] [blame] | 337 | bool CheckArgumentsPhiUses(); |
lrn@chromium.org | d4e9e22 | 2011-08-03 12:01:58 +0000 | [diff] [blame] | 338 | |
erik.corry@gmail.com | c3b670f | 2011-10-05 21:44:48 +0000 | [diff] [blame] | 339 | // Returns false if there are phi-uses of an uninitialized const |
| 340 | // which are not supported by the optimizing compiler. |
| 341 | bool CheckConstPhiUses(); |
| 342 | |
| 343 | void CollectPhis(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 344 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 345 | HConstant* GetConstantUndefined(); |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 346 | HConstant* GetConstant0(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 347 | HConstant* GetConstant1(); |
| 348 | HConstant* GetConstantMinus1(); |
| 349 | HConstant* GetConstantTrue(); |
| 350 | HConstant* GetConstantFalse(); |
ricow@chromium.org | d2be901 | 2011-06-01 06:00:58 +0000 | [diff] [blame] | 351 | HConstant* GetConstantHole(); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 352 | HConstant* GetConstantNull(); |
svenpanne@chromium.org | 876cca8 | 2013-03-18 14:43:20 +0000 | [diff] [blame] | 353 | HConstant* GetInvalidContext(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 354 | |
machenbach@chromium.org | 935a779 | 2013-11-12 09:05:18 +0000 | [diff] [blame] | 355 | bool IsConstantUndefined(HConstant* constant); |
| 356 | bool IsConstant0(HConstant* constant); |
| 357 | bool IsConstant1(HConstant* constant); |
| 358 | bool IsConstantMinus1(HConstant* constant); |
| 359 | bool IsConstantTrue(HConstant* constant); |
| 360 | bool IsConstantFalse(HConstant* constant); |
| 361 | bool IsConstantHole(HConstant* constant); |
| 362 | bool IsConstantNull(HConstant* constant); |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 363 | bool IsStandardConstant(HConstant* constant); |
| 364 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 365 | HBasicBlock* CreateBasicBlock(); |
| 366 | HArgumentsObject* GetArgumentsObject() const { |
| 367 | return arguments_object_.get(); |
| 368 | } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 369 | |
| 370 | void SetArgumentsObject(HArgumentsObject* object) { |
| 371 | arguments_object_.set(object); |
| 372 | } |
| 373 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 374 | int GetMaximumValueID() const { return values_.length(); } |
| 375 | int GetNextBlockID() { return next_block_id_++; } |
| 376 | int GetNextValueID(HValue* value) { |
machenbach@chromium.org | 935a779 | 2013-11-12 09:05:18 +0000 | [diff] [blame] | 377 | ASSERT(!disallow_adding_new_values_); |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 378 | values_.Add(value, zone()); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 379 | return values_.length() - 1; |
| 380 | } |
| 381 | HValue* LookupValue(int id) const { |
| 382 | if (id >= 0 && id < values_.length()) return values_[id]; |
| 383 | return NULL; |
| 384 | } |
machenbach@chromium.org | 935a779 | 2013-11-12 09:05:18 +0000 | [diff] [blame] | 385 | void DisallowAddingNewValues() { |
| 386 | disallow_adding_new_values_ = true; |
| 387 | } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 388 | |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 389 | bool Optimize(BailoutReason* bailout_reason); |
jkummerow@chromium.org | 28583c9 | 2012-07-16 11:31:55 +0000 | [diff] [blame] | 390 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 391 | #ifdef DEBUG |
erik.corry@gmail.com | c3b670f | 2011-10-05 21:44:48 +0000 | [diff] [blame] | 392 | void Verify(bool do_full_verify) const; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 393 | #endif |
| 394 | |
machenbach@chromium.org | c1789ee | 2013-07-05 07:09:57 +0000 | [diff] [blame] | 395 | bool has_osr() { |
| 396 | return osr_ != NULL; |
rossberg@chromium.org | 2c067b1 | 2012-03-19 11:01:52 +0000 | [diff] [blame] | 397 | } |
| 398 | |
machenbach@chromium.org | c1789ee | 2013-07-05 07:09:57 +0000 | [diff] [blame] | 399 | void set_osr(HOsrBuilder* osr) { |
| 400 | osr_ = osr; |
rossberg@chromium.org | 2c067b1 | 2012-03-19 11:01:52 +0000 | [diff] [blame] | 401 | } |
| 402 | |
machenbach@chromium.org | c1789ee | 2013-07-05 07:09:57 +0000 | [diff] [blame] | 403 | HOsrBuilder* osr() { |
| 404 | return osr_; |
rossberg@chromium.org | 2c067b1 | 2012-03-19 11:01:52 +0000 | [diff] [blame] | 405 | } |
| 406 | |
yangguo@chromium.org | 46839fb | 2012-08-28 09:06:19 +0000 | [diff] [blame] | 407 | int update_type_change_checksum(int delta) { |
| 408 | type_change_checksum_ += delta; |
| 409 | return type_change_checksum_; |
| 410 | } |
| 411 | |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 412 | void update_maximum_environment_size(int environment_size) { |
| 413 | if (environment_size > maximum_environment_size_) { |
| 414 | maximum_environment_size_ = environment_size; |
| 415 | } |
| 416 | } |
| 417 | int maximum_environment_size() { return maximum_environment_size_; } |
| 418 | |
yangguo@chromium.org | 46839fb | 2012-08-28 09:06:19 +0000 | [diff] [blame] | 419 | bool use_optimistic_licm() { |
| 420 | return use_optimistic_licm_; |
| 421 | } |
| 422 | |
| 423 | void set_use_optimistic_licm(bool value) { |
| 424 | use_optimistic_licm_ = value; |
| 425 | } |
| 426 | |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 427 | void MarkRecursive() { |
| 428 | is_recursive_ = true; |
| 429 | } |
| 430 | |
| 431 | bool is_recursive() const { |
| 432 | return is_recursive_; |
| 433 | } |
| 434 | |
ulan@chromium.org | 906e2fb | 2013-05-14 08:14:38 +0000 | [diff] [blame] | 435 | void MarkDependsOnEmptyArrayProtoElements() { |
danno@chromium.org | 4172848 | 2013-06-12 22:31:22 +0000 | [diff] [blame] | 436 | // Add map dependency if not already added. |
| 437 | if (depends_on_empty_array_proto_elements_) return; |
| 438 | isolate()->initial_object_prototype()->map()->AddDependentCompilationInfo( |
| 439 | DependentCode::kElementsCantBeAddedGroup, info()); |
| 440 | isolate()->initial_array_prototype()->map()->AddDependentCompilationInfo( |
| 441 | DependentCode::kElementsCantBeAddedGroup, info()); |
ulan@chromium.org | 906e2fb | 2013-05-14 08:14:38 +0000 | [diff] [blame] | 442 | depends_on_empty_array_proto_elements_ = true; |
| 443 | } |
| 444 | |
dslomov@chromium.org | b752d40 | 2013-06-18 11:54:54 +0000 | [diff] [blame] | 445 | bool depends_on_empty_array_proto_elements() { |
| 446 | return depends_on_empty_array_proto_elements_; |
| 447 | } |
| 448 | |
jkummerow@chromium.org | 93a47f4 | 2013-07-02 14:43:41 +0000 | [diff] [blame] | 449 | bool has_uint32_instructions() { |
| 450 | ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty()); |
| 451 | return uint32_instructions_ != NULL; |
| 452 | } |
| 453 | |
| 454 | ZoneList<HInstruction*>* uint32_instructions() { |
| 455 | ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty()); |
| 456 | return uint32_instructions_; |
| 457 | } |
| 458 | |
yangguo@chromium.org | 46839fb | 2012-08-28 09:06:19 +0000 | [diff] [blame] | 459 | void RecordUint32Instruction(HInstruction* instr) { |
jkummerow@chromium.org | 93a47f4 | 2013-07-02 14:43:41 +0000 | [diff] [blame] | 460 | ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty()); |
yangguo@chromium.org | 46839fb | 2012-08-28 09:06:19 +0000 | [diff] [blame] | 461 | if (uint32_instructions_ == NULL) { |
| 462 | uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone()); |
| 463 | } |
| 464 | uint32_instructions_->Add(instr, zone()); |
| 465 | } |
| 466 | |
danno@chromium.org | ad75d6f | 2013-08-12 16:57:59 +0000 | [diff] [blame] | 467 | void IncrementInNoSideEffectsScope() { no_side_effects_scope_count_++; } |
| 468 | void DecrementInNoSideEffectsScope() { no_side_effects_scope_count_--; } |
| 469 | bool IsInsideNoSideEffectsScope() { return no_side_effects_scope_count_ > 0; } |
| 470 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 471 | private: |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 472 | HConstant* ReinsertConstantIfNecessary(HConstant* constant); |
rossberg@chromium.org | b99c754 | 2013-05-31 11:40:45 +0000 | [diff] [blame] | 473 | HConstant* GetConstant(SetOncePointer<HConstant>* pointer, |
| 474 | int32_t integer_value); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 475 | |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 476 | template<class Phase> |
| 477 | void Run() { |
| 478 | Phase phase(this); |
| 479 | phase.Run(); |
| 480 | } |
| 481 | |
jkummerow@chromium.org | fb732b1 | 2013-07-26 10:27:09 +0000 | [diff] [blame] | 482 | void EliminateRedundantBoundsChecksUsingInductionVariables(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 483 | |
sgjesse@chromium.org | ea88ce9 | 2011-03-23 11:19:56 +0000 | [diff] [blame] | 484 | Isolate* isolate_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 485 | int next_block_id_; |
danno@chromium.org | 4d3fe4e | 2011-03-10 10:14:28 +0000 | [diff] [blame] | 486 | HBasicBlock* entry_block_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 487 | HEnvironment* start_environment_; |
| 488 | ZoneList<HBasicBlock*> blocks_; |
| 489 | ZoneList<HValue*> values_; |
| 490 | ZoneList<HPhi*>* phi_list_; |
yangguo@chromium.org | 46839fb | 2012-08-28 09:06:19 +0000 | [diff] [blame] | 491 | ZoneList<HInstruction*>* uint32_instructions_; |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 492 | SetOncePointer<HConstant> constant_undefined_; |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 493 | SetOncePointer<HConstant> constant_0_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 494 | SetOncePointer<HConstant> constant_1_; |
| 495 | SetOncePointer<HConstant> constant_minus1_; |
| 496 | SetOncePointer<HConstant> constant_true_; |
| 497 | SetOncePointer<HConstant> constant_false_; |
svenpanne@chromium.org | 2bda543 | 2013-03-15 12:39:50 +0000 | [diff] [blame] | 498 | SetOncePointer<HConstant> constant_the_hole_; |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 499 | SetOncePointer<HConstant> constant_null_; |
svenpanne@chromium.org | 876cca8 | 2013-03-18 14:43:20 +0000 | [diff] [blame] | 500 | SetOncePointer<HConstant> constant_invalid_context_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 501 | SetOncePointer<HArgumentsObject> arguments_object_; |
| 502 | |
machenbach@chromium.org | c1789ee | 2013-07-05 07:09:57 +0000 | [diff] [blame] | 503 | HOsrBuilder* osr_; |
rossberg@chromium.org | 2c067b1 | 2012-03-19 11:01:52 +0000 | [diff] [blame] | 504 | |
yangguo@chromium.org | 5a11aaf | 2012-06-20 11:29:00 +0000 | [diff] [blame] | 505 | CompilationInfo* info_; |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 506 | Zone* zone_; |
| 507 | |
| 508 | bool is_recursive_; |
yangguo@chromium.org | 46839fb | 2012-08-28 09:06:19 +0000 | [diff] [blame] | 509 | bool use_optimistic_licm_; |
ulan@chromium.org | 906e2fb | 2013-05-14 08:14:38 +0000 | [diff] [blame] | 510 | bool depends_on_empty_array_proto_elements_; |
yangguo@chromium.org | 46839fb | 2012-08-28 09:06:19 +0000 | [diff] [blame] | 511 | int type_change_checksum_; |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 512 | int maximum_environment_size_; |
danno@chromium.org | ad75d6f | 2013-08-12 16:57:59 +0000 | [diff] [blame] | 513 | int no_side_effects_scope_count_; |
machenbach@chromium.org | 935a779 | 2013-11-12 09:05:18 +0000 | [diff] [blame] | 514 | bool disallow_adding_new_values_; |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 515 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 516 | DISALLOW_COPY_AND_ASSIGN(HGraph); |
| 517 | }; |
| 518 | |
| 519 | |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 520 | Zone* HBasicBlock::zone() const { return graph_->zone(); } |
vegorov@chromium.org | 74f333b | 2011-04-06 11:17:46 +0000 | [diff] [blame] | 521 | |
| 522 | |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 523 | // Type of stack frame an environment might refer to. |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 524 | enum FrameType { |
| 525 | JS_FUNCTION, |
| 526 | JS_CONSTRUCT, |
mstarzinger@chromium.org | de88679 | 2012-09-11 13:22:37 +0000 | [diff] [blame] | 527 | JS_GETTER, |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 528 | JS_SETTER, |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 529 | ARGUMENTS_ADAPTOR, |
| 530 | STUB |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 531 | }; |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 532 | |
| 533 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 534 | class HEnvironment V8_FINAL : public ZoneObject { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 535 | public: |
| 536 | HEnvironment(HEnvironment* outer, |
| 537 | Scope* scope, |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 538 | Handle<JSFunction> closure, |
| 539 | Zone* zone); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 540 | |
ulan@chromium.org | 09d7ab5 | 2013-02-25 15:50:35 +0000 | [diff] [blame] | 541 | HEnvironment(Zone* zone, int parameter_count); |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 542 | |
ulan@chromium.org | 6ff6514 | 2012-03-21 09:52:17 +0000 | [diff] [blame] | 543 | HEnvironment* arguments_environment() { |
| 544 | return outer()->frame_type() == ARGUMENTS_ADAPTOR ? outer() : this; |
| 545 | } |
| 546 | |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 547 | // Simple accessors. |
| 548 | Handle<JSFunction> closure() const { return closure_; } |
| 549 | const ZoneList<HValue*>* values() const { return &values_; } |
jkummerow@chromium.org | 59297c7 | 2013-01-09 16:32:23 +0000 | [diff] [blame] | 550 | const GrowableBitVector* assigned_variables() const { |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 551 | return &assigned_variables_; |
| 552 | } |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 553 | FrameType frame_type() const { return frame_type_; } |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 554 | int parameter_count() const { return parameter_count_; } |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 555 | int specials_count() const { return specials_count_; } |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 556 | int local_count() const { return local_count_; } |
| 557 | HEnvironment* outer() const { return outer_; } |
| 558 | int pop_count() const { return pop_count_; } |
| 559 | int push_count() const { return push_count_; } |
| 560 | |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 561 | BailoutId ast_id() const { return ast_id_; } |
| 562 | void set_ast_id(BailoutId id) { ast_id_ = id; } |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 563 | |
ulan@chromium.org | 56c14af | 2012-09-20 12:51:09 +0000 | [diff] [blame] | 564 | HEnterInlined* entry() const { return entry_; } |
| 565 | void set_entry(HEnterInlined* entry) { entry_ = entry; } |
| 566 | |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 567 | int length() const { return values_.length(); } |
| 568 | |
kmillikin@chromium.org | be6bd10 | 2012-02-23 08:45:21 +0000 | [diff] [blame] | 569 | int first_expression_index() const { |
| 570 | return parameter_count() + specials_count() + local_count(); |
| 571 | } |
| 572 | |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 573 | int first_local_index() const { |
| 574 | return parameter_count() + specials_count(); |
| 575 | } |
| 576 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 577 | void Bind(Variable* variable, HValue* value) { |
| 578 | Bind(IndexFor(variable), value); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 579 | } |
| 580 | |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 581 | void Bind(int index, HValue* value); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 582 | |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 583 | void BindContext(HValue* value) { |
| 584 | Bind(parameter_count(), value); |
| 585 | } |
| 586 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 587 | HValue* Lookup(Variable* variable) const { |
| 588 | return Lookup(IndexFor(variable)); |
| 589 | } |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 590 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 591 | HValue* Lookup(int index) const { |
| 592 | HValue* result = values_[index]; |
| 593 | ASSERT(result != NULL); |
| 594 | return result; |
| 595 | } |
| 596 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 597 | HValue* context() const { |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 598 | // Return first special. |
| 599 | return Lookup(parameter_count()); |
| 600 | } |
| 601 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 602 | void Push(HValue* value) { |
| 603 | ASSERT(value != NULL); |
| 604 | ++push_count_; |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 605 | values_.Add(value, zone()); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 606 | } |
| 607 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 608 | HValue* Pop() { |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 609 | ASSERT(!ExpressionStackIsEmpty()); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 610 | if (push_count_ > 0) { |
| 611 | --push_count_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 612 | } else { |
| 613 | ++pop_count_; |
| 614 | } |
| 615 | return values_.RemoveLast(); |
| 616 | } |
| 617 | |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 618 | void Drop(int count); |
| 619 | |
| 620 | HValue* Top() const { return ExpressionStackAt(0); } |
| 621 | |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 622 | bool ExpressionStackIsEmpty() const; |
| 623 | |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 624 | HValue* ExpressionStackAt(int index_from_top) const { |
| 625 | int index = length() - index_from_top - 1; |
| 626 | ASSERT(HasExpressionAt(index)); |
| 627 | return values_[index]; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 628 | } |
| 629 | |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 630 | void SetExpressionStackAt(int index_from_top, HValue* value); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 631 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 632 | HEnvironment* Copy() const; |
| 633 | HEnvironment* CopyWithoutHistory() const; |
| 634 | HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const; |
| 635 | |
| 636 | // Create an "inlined version" of this environment, where the original |
| 637 | // environment is the outer environment but the top expression stack |
vegorov@chromium.org | 3cf4731 | 2011-06-29 13:20:01 +0000 | [diff] [blame] | 638 | // elements are moved to an inner environment as parameters. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 639 | HEnvironment* CopyForInlining(Handle<JSFunction> target, |
yangguo@chromium.org | 659ceec | 2012-01-26 07:37:54 +0000 | [diff] [blame] | 640 | int arguments, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 641 | FunctionLiteral* function, |
danno@chromium.org | 40cb878 | 2011-05-25 07:58:50 +0000 | [diff] [blame] | 642 | HConstant* undefined, |
yangguo@chromium.org | 003650e | 2013-01-24 16:31:08 +0000 | [diff] [blame] | 643 | InliningKind inlining_kind, |
| 644 | bool undefined_receiver) const; |
| 645 | |
| 646 | static bool UseUndefinedReceiver(Handle<JSFunction> closure, |
| 647 | FunctionLiteral* function, |
| 648 | CallKind call_kind, |
| 649 | InliningKind inlining_kind) { |
| 650 | return (closure->shared()->native() || !function->is_classic_mode()) && |
| 651 | call_kind == CALL_AS_FUNCTION && inlining_kind != CONSTRUCT_CALL_RETURN; |
| 652 | } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 653 | |
ulan@chromium.org | 56c14af | 2012-09-20 12:51:09 +0000 | [diff] [blame] | 654 | HEnvironment* DiscardInlined(bool drop_extra) { |
| 655 | HEnvironment* outer = outer_; |
| 656 | while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_; |
| 657 | if (drop_extra) outer->Drop(1); |
| 658 | return outer; |
| 659 | } |
| 660 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 661 | void AddIncomingEdge(HBasicBlock* block, HEnvironment* other); |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 662 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 663 | void ClearHistory() { |
| 664 | pop_count_ = 0; |
| 665 | push_count_ = 0; |
jkummerow@chromium.org | 59297c7 | 2013-01-09 16:32:23 +0000 | [diff] [blame] | 666 | assigned_variables_.Clear(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 667 | } |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 668 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 669 | void SetValueAt(int index, HValue* value) { |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 670 | ASSERT(index < length()); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 671 | values_[index] = value; |
| 672 | } |
| 673 | |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 674 | // Map a variable to an environment index. Parameter indices are shifted |
| 675 | // by 1 (receiver is parameter index -1 but environment index 0). |
| 676 | // Stack-allocated local indices are shifted by the number of parameters. |
| 677 | int IndexFor(Variable* variable) const { |
| 678 | ASSERT(variable->IsStackAllocated()); |
| 679 | int shift = variable->IsParameter() |
| 680 | ? 1 |
| 681 | : parameter_count_ + specials_count_; |
| 682 | return variable->index() + shift; |
| 683 | } |
| 684 | |
| 685 | bool is_local_index(int i) const { |
hpayer@chromium.org | c5d4971 | 2013-09-11 08:25:48 +0000 | [diff] [blame] | 686 | return i >= first_local_index() && i < first_expression_index(); |
| 687 | } |
| 688 | |
| 689 | bool is_parameter_index(int i) const { |
| 690 | return i >= 0 && i < parameter_count(); |
| 691 | } |
| 692 | |
| 693 | bool is_special_index(int i) const { |
| 694 | return i >= parameter_count() && i < parameter_count() + specials_count(); |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 695 | } |
| 696 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 697 | void PrintTo(StringStream* stream); |
| 698 | void PrintToStd(); |
| 699 | |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 700 | Zone* zone() const { return zone_; } |
| 701 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 702 | private: |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 703 | HEnvironment(const HEnvironment* other, Zone* zone); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 704 | |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 705 | HEnvironment(HEnvironment* outer, |
| 706 | Handle<JSFunction> closure, |
| 707 | FrameType frame_type, |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 708 | int arguments, |
| 709 | Zone* zone); |
yangguo@chromium.org | 659ceec | 2012-01-26 07:37:54 +0000 | [diff] [blame] | 710 | |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 711 | // Create an artificial stub environment (e.g. for argument adaptor or |
| 712 | // constructor stub). |
| 713 | HEnvironment* CreateStubEnvironment(HEnvironment* outer, |
| 714 | Handle<JSFunction> target, |
| 715 | FrameType frame_type, |
| 716 | int arguments) const; |
yangguo@chromium.org | 659ceec | 2012-01-26 07:37:54 +0000 | [diff] [blame] | 717 | |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 718 | // True if index is included in the expression stack part of the environment. |
| 719 | bool HasExpressionAt(int index) const; |
| 720 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 721 | void Initialize(int parameter_count, int local_count, int stack_height); |
| 722 | void Initialize(const HEnvironment* other); |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 723 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 724 | Handle<JSFunction> closure_; |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 725 | // Value array [parameters] [specials] [locals] [temporaries]. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 726 | ZoneList<HValue*> values_; |
jkummerow@chromium.org | 59297c7 | 2013-01-09 16:32:23 +0000 | [diff] [blame] | 727 | GrowableBitVector assigned_variables_; |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 728 | FrameType frame_type_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 729 | int parameter_count_; |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 730 | int specials_count_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 731 | int local_count_; |
| 732 | HEnvironment* outer_; |
ulan@chromium.org | 56c14af | 2012-09-20 12:51:09 +0000 | [diff] [blame] | 733 | HEnterInlined* entry_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 734 | int pop_count_; |
| 735 | int push_count_; |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 736 | BailoutId ast_id_; |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 737 | Zone* zone_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 738 | }; |
| 739 | |
| 740 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 741 | class HOptimizedGraphBuilder; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 742 | |
sgjesse@chromium.org | 8e8294a | 2011-05-02 14:30:53 +0000 | [diff] [blame] | 743 | enum ArgumentsAllowedFlag { |
| 744 | ARGUMENTS_NOT_ALLOWED, |
| 745 | ARGUMENTS_ALLOWED |
| 746 | }; |
| 747 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 748 | |
| 749 | class HIfContinuation; |
| 750 | |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 751 | // This class is not BASE_EMBEDDED because our inlining implementation uses |
| 752 | // new and delete. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 753 | class AstContext { |
| 754 | public: |
| 755 | bool IsEffect() const { return kind_ == Expression::kEffect; } |
| 756 | bool IsValue() const { return kind_ == Expression::kValue; } |
| 757 | bool IsTest() const { return kind_ == Expression::kTest; } |
| 758 | |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 759 | // 'Fill' this context with a hydrogen value. The value is assumed to |
| 760 | // have already been inserted in the instruction stream (or not need to |
| 761 | // be, e.g., HPhi). Call this function in tail position in the Visit |
| 762 | // functions for expressions. |
| 763 | virtual void ReturnValue(HValue* value) = 0; |
| 764 | |
| 765 | // Add a hydrogen instruction to the instruction stream (recording an |
| 766 | // environment simulation if necessary) and then fill this context with |
| 767 | // the instruction as value. |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 768 | virtual void ReturnInstruction(HInstruction* instr, BailoutId ast_id) = 0; |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 769 | |
ricow@chromium.org | 4f693d6 | 2011-07-04 14:01:31 +0000 | [diff] [blame] | 770 | // Finishes the current basic block and materialize a boolean for |
| 771 | // value context, nothing for effect, generate a branch for test context. |
| 772 | // Call this function in tail position in the Visit functions for |
| 773 | // expressions. |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 774 | virtual void ReturnControl(HControlInstruction* instr, BailoutId ast_id) = 0; |
ricow@chromium.org | 4f693d6 | 2011-07-04 14:01:31 +0000 | [diff] [blame] | 775 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 776 | // Finishes the current basic block and materialize a boolean for |
| 777 | // value context, nothing for effect, generate a branch for test context. |
| 778 | // Call this function in tail position in the Visit functions for |
| 779 | // expressions that use an IfBuilder. |
| 780 | virtual void ReturnContinuation(HIfContinuation* continuation, |
| 781 | BailoutId ast_id) = 0; |
| 782 | |
kmillikin@chromium.org | c36ce6e | 2011-04-04 08:25:31 +0000 | [diff] [blame] | 783 | void set_for_typeof(bool for_typeof) { for_typeof_ = for_typeof; } |
| 784 | bool is_for_typeof() { return for_typeof_; } |
| 785 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 786 | protected: |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 787 | AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 788 | virtual ~AstContext(); |
| 789 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 790 | HOptimizedGraphBuilder* owner() const { return owner_; } |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 791 | |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 792 | inline Zone* zone() const; |
vegorov@chromium.org | 74f333b | 2011-04-06 11:17:46 +0000 | [diff] [blame] | 793 | |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 794 | // We want to be able to assert, in a context-specific way, that the stack |
| 795 | // height makes sense when the context is filled. |
| 796 | #ifdef DEBUG |
lrn@chromium.org | 5d00b60 | 2011-01-05 09:51:43 +0000 | [diff] [blame] | 797 | int original_length_; |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 798 | #endif |
| 799 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 800 | private: |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 801 | HOptimizedGraphBuilder* owner_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 802 | Expression::Context kind_; |
| 803 | AstContext* outer_; |
kmillikin@chromium.org | c36ce6e | 2011-04-04 08:25:31 +0000 | [diff] [blame] | 804 | bool for_typeof_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 805 | }; |
| 806 | |
| 807 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 808 | class EffectContext V8_FINAL : public AstContext { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 809 | public: |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 810 | explicit EffectContext(HOptimizedGraphBuilder* owner) |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 811 | : AstContext(owner, Expression::kEffect) { |
| 812 | } |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 813 | virtual ~EffectContext(); |
| 814 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 815 | virtual void ReturnValue(HValue* value) V8_OVERRIDE; |
| 816 | virtual void ReturnInstruction(HInstruction* instr, |
| 817 | BailoutId ast_id) V8_OVERRIDE; |
| 818 | virtual void ReturnControl(HControlInstruction* instr, |
| 819 | BailoutId ast_id) V8_OVERRIDE; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 820 | virtual void ReturnContinuation(HIfContinuation* continuation, |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 821 | BailoutId ast_id) V8_OVERRIDE; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 822 | }; |
| 823 | |
| 824 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 825 | class ValueContext V8_FINAL : public AstContext { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 826 | public: |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 827 | ValueContext(HOptimizedGraphBuilder* owner, ArgumentsAllowedFlag flag) |
sgjesse@chromium.org | 8e8294a | 2011-05-02 14:30:53 +0000 | [diff] [blame] | 828 | : AstContext(owner, Expression::kValue), flag_(flag) { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 829 | } |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 830 | virtual ~ValueContext(); |
| 831 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 832 | virtual void ReturnValue(HValue* value) V8_OVERRIDE; |
| 833 | virtual void ReturnInstruction(HInstruction* instr, |
| 834 | BailoutId ast_id) V8_OVERRIDE; |
| 835 | virtual void ReturnControl(HControlInstruction* instr, |
| 836 | BailoutId ast_id) V8_OVERRIDE; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 837 | virtual void ReturnContinuation(HIfContinuation* continuation, |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 838 | BailoutId ast_id) V8_OVERRIDE; |
sgjesse@chromium.org | 8e8294a | 2011-05-02 14:30:53 +0000 | [diff] [blame] | 839 | |
| 840 | bool arguments_allowed() { return flag_ == ARGUMENTS_ALLOWED; } |
| 841 | |
| 842 | private: |
| 843 | ArgumentsAllowedFlag flag_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 844 | }; |
| 845 | |
| 846 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 847 | class TestContext V8_FINAL : public AstContext { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 848 | public: |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 849 | TestContext(HOptimizedGraphBuilder* owner, |
svenpanne@chromium.org | 6d786c9 | 2011-06-15 10:58:27 +0000 | [diff] [blame] | 850 | Expression* condition, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 851 | HBasicBlock* if_true, |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 852 | HBasicBlock* if_false) |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 853 | : AstContext(owner, Expression::kTest), |
svenpanne@chromium.org | 6d786c9 | 2011-06-15 10:58:27 +0000 | [diff] [blame] | 854 | condition_(condition), |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 855 | if_true_(if_true), |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 856 | if_false_(if_false) { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 857 | } |
| 858 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 859 | virtual void ReturnValue(HValue* value) V8_OVERRIDE; |
| 860 | virtual void ReturnInstruction(HInstruction* instr, |
| 861 | BailoutId ast_id) V8_OVERRIDE; |
| 862 | virtual void ReturnControl(HControlInstruction* instr, |
| 863 | BailoutId ast_id) V8_OVERRIDE; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 864 | virtual void ReturnContinuation(HIfContinuation* continuation, |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 865 | BailoutId ast_id) V8_OVERRIDE; |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 866 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 867 | static TestContext* cast(AstContext* context) { |
| 868 | ASSERT(context->IsTest()); |
| 869 | return reinterpret_cast<TestContext*>(context); |
| 870 | } |
| 871 | |
svenpanne@chromium.org | 6d786c9 | 2011-06-15 10:58:27 +0000 | [diff] [blame] | 872 | Expression* condition() const { return condition_; } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 873 | HBasicBlock* if_true() const { return if_true_; } |
| 874 | HBasicBlock* if_false() const { return if_false_; } |
| 875 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 876 | private: |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 877 | // Build the shared core part of the translation unpacking a value into |
| 878 | // control flow. |
| 879 | void BuildBranch(HValue* value); |
| 880 | |
svenpanne@chromium.org | 6d786c9 | 2011-06-15 10:58:27 +0000 | [diff] [blame] | 881 | Expression* condition_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 882 | HBasicBlock* if_true_; |
| 883 | HBasicBlock* if_false_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 884 | }; |
| 885 | |
| 886 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 887 | class FunctionState V8_FINAL { |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 888 | public: |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 889 | FunctionState(HOptimizedGraphBuilder* owner, |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 890 | CompilationInfo* info, |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 891 | InliningKind inlining_kind); |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 892 | ~FunctionState(); |
| 893 | |
| 894 | CompilationInfo* compilation_info() { return compilation_info_; } |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 895 | AstContext* call_context() { return call_context_; } |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 896 | InliningKind inlining_kind() const { return inlining_kind_; } |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 897 | HBasicBlock* function_return() { return function_return_; } |
| 898 | TestContext* test_context() { return test_context_; } |
| 899 | void ClearInlinedTestContext() { |
| 900 | delete test_context_; |
| 901 | test_context_ = NULL; |
| 902 | } |
| 903 | |
kmillikin@chromium.org | c36ce6e | 2011-04-04 08:25:31 +0000 | [diff] [blame] | 904 | FunctionState* outer() { return outer_; } |
| 905 | |
jkummerow@chromium.org | 28faa98 | 2012-04-13 09:58:30 +0000 | [diff] [blame] | 906 | HEnterInlined* entry() { return entry_; } |
| 907 | void set_entry(HEnterInlined* entry) { entry_ = entry; } |
| 908 | |
dslomov@chromium.org | b752d40 | 2013-06-18 11:54:54 +0000 | [diff] [blame] | 909 | HArgumentsObject* arguments_object() { return arguments_object_; } |
| 910 | void set_arguments_object(HArgumentsObject* arguments_object) { |
| 911 | arguments_object_ = arguments_object; |
| 912 | } |
| 913 | |
jkummerow@chromium.org | 28faa98 | 2012-04-13 09:58:30 +0000 | [diff] [blame] | 914 | HArgumentsElements* arguments_elements() { return arguments_elements_; } |
| 915 | void set_arguments_elements(HArgumentsElements* arguments_elements) { |
| 916 | arguments_elements_ = arguments_elements; |
| 917 | } |
| 918 | |
| 919 | bool arguments_pushed() { return arguments_elements() != NULL; } |
| 920 | |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 921 | private: |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 922 | HOptimizedGraphBuilder* owner_; |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 923 | |
| 924 | CompilationInfo* compilation_info_; |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 925 | |
| 926 | // During function inlining, expression context of the call being |
| 927 | // inlined. NULL when not inlining. |
| 928 | AstContext* call_context_; |
| 929 | |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 930 | // The kind of call which is currently being inlined. |
| 931 | InliningKind inlining_kind_; |
erik.corry@gmail.com | 394dbcf | 2011-10-27 07:38:48 +0000 | [diff] [blame] | 932 | |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 933 | // When inlining in an effect or value context, this is the return block. |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 934 | // It is NULL otherwise. When inlining in a test context, there are a |
| 935 | // pair of return blocks in the context. When not inlining, there is no |
| 936 | // local return point. |
| 937 | HBasicBlock* function_return_; |
| 938 | |
| 939 | // When inlining a call in a test context, a context containing a pair of |
| 940 | // return blocks. NULL in all other cases. |
| 941 | TestContext* test_context_; |
| 942 | |
jkummerow@chromium.org | 28faa98 | 2012-04-13 09:58:30 +0000 | [diff] [blame] | 943 | // When inlining HEnterInlined instruction corresponding to the function |
| 944 | // entry. |
| 945 | HEnterInlined* entry_; |
| 946 | |
dslomov@chromium.org | b752d40 | 2013-06-18 11:54:54 +0000 | [diff] [blame] | 947 | HArgumentsObject* arguments_object_; |
jkummerow@chromium.org | 28faa98 | 2012-04-13 09:58:30 +0000 | [diff] [blame] | 948 | HArgumentsElements* arguments_elements_; |
| 949 | |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 950 | FunctionState* outer_; |
| 951 | }; |
| 952 | |
| 953 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 954 | class HIfContinuation V8_FINAL { |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 955 | public: |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame^] | 956 | HIfContinuation() |
| 957 | : continuation_captured_(false), |
| 958 | true_branch_(NULL), |
| 959 | false_branch_(NULL) {} |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 960 | HIfContinuation(HBasicBlock* true_branch, |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 961 | HBasicBlock* false_branch) |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 962 | : continuation_captured_(true), true_branch_(true_branch), |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 963 | false_branch_(false_branch) {} |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 964 | ~HIfContinuation() { ASSERT(!continuation_captured_); } |
| 965 | |
| 966 | void Capture(HBasicBlock* true_branch, |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 967 | HBasicBlock* false_branch) { |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 968 | ASSERT(!continuation_captured_); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 969 | true_branch_ = true_branch; |
| 970 | false_branch_ = false_branch; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 971 | continuation_captured_ = true; |
| 972 | } |
| 973 | |
| 974 | void Continue(HBasicBlock** true_branch, |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 975 | HBasicBlock** false_branch) { |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 976 | ASSERT(continuation_captured_); |
| 977 | *true_branch = true_branch_; |
| 978 | *false_branch = false_branch_; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 979 | continuation_captured_ = false; |
| 980 | } |
| 981 | |
| 982 | bool IsTrueReachable() { return true_branch_ != NULL; } |
| 983 | bool IsFalseReachable() { return false_branch_ != NULL; } |
| 984 | bool TrueAndFalseReachable() { |
| 985 | return IsTrueReachable() || IsFalseReachable(); |
| 986 | } |
| 987 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 988 | HBasicBlock* true_branch() const { return true_branch_; } |
| 989 | HBasicBlock* false_branch() const { return false_branch_; } |
| 990 | |
| 991 | private: |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 992 | bool continuation_captured_; |
| 993 | HBasicBlock* true_branch_; |
| 994 | HBasicBlock* false_branch_; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 995 | }; |
| 996 | |
| 997 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 998 | class HGraphBuilder { |
| 999 | public: |
| 1000 | explicit HGraphBuilder(CompilationInfo* info) |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 1001 | : info_(info), |
| 1002 | graph_(NULL), |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1003 | current_block_(NULL), |
| 1004 | position_(RelocInfo::kNoPosition) {} |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1005 | virtual ~HGraphBuilder() {} |
| 1006 | |
| 1007 | HBasicBlock* current_block() const { return current_block_; } |
| 1008 | void set_current_block(HBasicBlock* block) { current_block_ = block; } |
| 1009 | HEnvironment* environment() const { |
| 1010 | return current_block()->last_environment(); |
| 1011 | } |
| 1012 | Zone* zone() const { return info_->zone(); } |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 1013 | HGraph* graph() const { return graph_; } |
| 1014 | Isolate* isolate() const { return graph_->isolate(); } |
danno@chromium.org | 4172848 | 2013-06-12 22:31:22 +0000 | [diff] [blame] | 1015 | CompilationInfo* top_info() { return info_; } |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1016 | |
| 1017 | HGraph* CreateGraph(); |
| 1018 | |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1019 | // Bailout environment manipulation. |
| 1020 | void Push(HValue* value) { environment()->Push(value); } |
| 1021 | HValue* Pop() { return environment()->Pop(); } |
| 1022 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1023 | virtual HValue* context() = 0; |
| 1024 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1025 | // Adding instructions. |
| 1026 | HInstruction* AddInstruction(HInstruction* instr); |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1027 | void FinishCurrentBlock(HControlInstruction* last); |
| 1028 | void FinishExitCurrentBlock(HControlInstruction* instruction); |
| 1029 | |
| 1030 | void Goto(HBasicBlock* from, |
| 1031 | HBasicBlock* target, |
| 1032 | FunctionState* state = NULL, |
| 1033 | bool add_simulate = true) { |
| 1034 | from->Goto(target, position_, state, add_simulate); |
| 1035 | } |
| 1036 | void Goto(HBasicBlock* target, |
| 1037 | FunctionState* state = NULL, |
| 1038 | bool add_simulate = true) { |
| 1039 | Goto(current_block(), target, state, add_simulate); |
| 1040 | } |
| 1041 | void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) { |
| 1042 | Goto(from, target, NULL, false); |
| 1043 | } |
| 1044 | void GotoNoSimulate(HBasicBlock* target) { |
| 1045 | Goto(target, NULL, false); |
| 1046 | } |
| 1047 | void AddLeaveInlined(HBasicBlock* block, |
| 1048 | HValue* return_value, |
| 1049 | FunctionState* state) { |
| 1050 | block->AddLeaveInlined(return_value, state, position_); |
| 1051 | } |
| 1052 | void AddLeaveInlined(HValue* return_value, FunctionState* state) { |
| 1053 | return AddLeaveInlined(current_block(), return_value, state); |
| 1054 | } |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1055 | |
| 1056 | template<class I> |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1057 | HInstruction* NewUncasted() { return I::New(zone(), context()); } |
| 1058 | |
| 1059 | template<class I> |
| 1060 | I* New() { return I::cast(NewUncasted<I>()); } |
| 1061 | |
| 1062 | template<class I> |
| 1063 | HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());} |
| 1064 | |
| 1065 | template<class I> |
| 1066 | I* Add() { return I::cast(AddUncasted<I>());} |
| 1067 | |
| 1068 | template<class I, class P1> |
| 1069 | HInstruction* NewUncasted(P1 p1) { |
| 1070 | return I::New(zone(), context(), p1); |
| 1071 | } |
| 1072 | |
| 1073 | template<class I, class P1> |
| 1074 | I* New(P1 p1) { return I::cast(NewUncasted<I>(p1)); } |
| 1075 | |
| 1076 | template<class I, class P1> |
| 1077 | HInstruction* AddUncasted(P1 p1) { |
| 1078 | HInstruction* result = AddInstruction(NewUncasted<I>(p1)); |
| 1079 | // Specializations must have their parameters properly casted |
| 1080 | // to avoid landing here. |
| 1081 | ASSERT(!result->IsReturn() && !result->IsSimulate() && |
| 1082 | !result->IsDeoptimize()); |
| 1083 | return result; |
| 1084 | } |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1085 | |
| 1086 | template<class I, class P1> |
| 1087 | I* Add(P1 p1) { |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1088 | return I::cast(AddUncasted<I>(p1)); |
| 1089 | } |
| 1090 | |
| 1091 | template<class I, class P1, class P2> |
| 1092 | HInstruction* NewUncasted(P1 p1, P2 p2) { |
| 1093 | return I::New(zone(), context(), p1, p2); |
| 1094 | } |
| 1095 | |
| 1096 | template<class I, class P1, class P2> |
| 1097 | I* New(P1 p1, P2 p2) { |
| 1098 | return I::cast(NewUncasted<I>(p1, p2)); |
| 1099 | } |
| 1100 | |
| 1101 | template<class I, class P1, class P2> |
| 1102 | HInstruction* AddUncasted(P1 p1, P2 p2) { |
| 1103 | HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2)); |
| 1104 | // Specializations must have their parameters properly casted |
| 1105 | // to avoid landing here. |
| 1106 | ASSERT(!result->IsSimulate()); |
| 1107 | return result; |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1108 | } |
| 1109 | |
| 1110 | template<class I, class P1, class P2> |
| 1111 | I* Add(P1 p1, P2 p2) { |
verwaest@chromium.org | 662436e | 2013-08-28 08:41:27 +0000 | [diff] [blame] | 1112 | return I::cast(AddUncasted<I>(p1, p2)); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1113 | } |
| 1114 | |
| 1115 | template<class I, class P1, class P2, class P3> |
| 1116 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) { |
| 1117 | return I::New(zone(), context(), p1, p2, p3); |
| 1118 | } |
| 1119 | |
| 1120 | template<class I, class P1, class P2, class P3> |
| 1121 | I* New(P1 p1, P2 p2, P3 p3) { |
| 1122 | return I::cast(NewUncasted<I>(p1, p2, p3)); |
| 1123 | } |
| 1124 | |
| 1125 | template<class I, class P1, class P2, class P3> |
| 1126 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) { |
| 1127 | return AddInstruction(NewUncasted<I>(p1, p2, p3)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1128 | } |
| 1129 | |
| 1130 | template<class I, class P1, class P2, class P3> |
| 1131 | I* Add(P1 p1, P2 p2, P3 p3) { |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1132 | return I::cast(AddUncasted<I>(p1, p2, p3)); |
| 1133 | } |
| 1134 | |
| 1135 | template<class I, class P1, class P2, class P3, class P4> |
| 1136 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) { |
| 1137 | return I::New(zone(), context(), p1, p2, p3, p4); |
| 1138 | } |
| 1139 | |
| 1140 | template<class I, class P1, class P2, class P3, class P4> |
| 1141 | I* New(P1 p1, P2 p2, P3 p3, P4 p4) { |
| 1142 | return I::cast(NewUncasted<I>(p1, p2, p3, p4)); |
| 1143 | } |
| 1144 | |
| 1145 | template<class I, class P1, class P2, class P3, class P4> |
| 1146 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) { |
| 1147 | return AddInstruction(NewUncasted<I>(p1, p2, p3, p4)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1148 | } |
| 1149 | |
| 1150 | template<class I, class P1, class P2, class P3, class P4> |
| 1151 | I* Add(P1 p1, P2 p2, P3 p3, P4 p4) { |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1152 | return I::cast(AddUncasted<I>(p1, p2, p3, p4)); |
| 1153 | } |
| 1154 | |
| 1155 | template<class I, class P1, class P2, class P3, class P4, class P5> |
| 1156 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { |
| 1157 | return I::New(zone(), context(), p1, p2, p3, p4, p5); |
| 1158 | } |
| 1159 | |
| 1160 | template<class I, class P1, class P2, class P3, class P4, class P5> |
| 1161 | I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { |
| 1162 | return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5)); |
| 1163 | } |
| 1164 | |
| 1165 | template<class I, class P1, class P2, class P3, class P4, class P5> |
| 1166 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { |
| 1167 | return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1168 | } |
| 1169 | |
| 1170 | template<class I, class P1, class P2, class P3, class P4, class P5> |
| 1171 | I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1172 | return I::cast(AddUncasted<I>(p1, p2, p3, p4, p5)); |
| 1173 | } |
| 1174 | |
| 1175 | template<class I, class P1, class P2, class P3, class P4, class P5, class P6> |
| 1176 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { |
| 1177 | return I::New(zone(), context(), p1, p2, p3, p4, p5, p6); |
| 1178 | } |
| 1179 | |
| 1180 | template<class I, class P1, class P2, class P3, class P4, class P5, class P6> |
| 1181 | I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { |
| 1182 | return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6)); |
| 1183 | } |
| 1184 | |
| 1185 | template<class I, class P1, class P2, class P3, class P4, class P5, class P6> |
| 1186 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { |
| 1187 | return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1188 | } |
| 1189 | |
| 1190 | template<class I, class P1, class P2, class P3, class P4, class P5, class P6> |
| 1191 | I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1192 | return I::cast(AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6))); |
| 1193 | } |
| 1194 | |
| 1195 | template<class I, class P1, class P2, class P3, class P4, |
| 1196 | class P5, class P6, class P7> |
| 1197 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { |
| 1198 | return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7); |
| 1199 | } |
| 1200 | |
| 1201 | template<class I, class P1, class P2, class P3, class P4, |
| 1202 | class P5, class P6, class P7> |
| 1203 | I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { |
| 1204 | return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7)); |
| 1205 | } |
| 1206 | |
| 1207 | template<class I, class P1, class P2, class P3, |
| 1208 | class P4, class P5, class P6, class P7> |
| 1209 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { |
| 1210 | return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1211 | } |
| 1212 | |
| 1213 | template<class I, class P1, class P2, class P3, |
| 1214 | class P4, class P5, class P6, class P7> |
| 1215 | I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1216 | return I::cast(AddInstruction(NewUncasted<I>(p1, p2, p3, p4, |
| 1217 | p5, p6, p7))); |
| 1218 | } |
| 1219 | |
| 1220 | template<class I, class P1, class P2, class P3, class P4, |
| 1221 | class P5, class P6, class P7, class P8> |
| 1222 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, |
| 1223 | P5 p5, P6 p6, P7 p7, P8 p8) { |
| 1224 | return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8); |
| 1225 | } |
| 1226 | |
| 1227 | template<class I, class P1, class P2, class P3, class P4, |
| 1228 | class P5, class P6, class P7, class P8> |
| 1229 | I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) { |
| 1230 | return I::cast(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8)); |
| 1231 | } |
| 1232 | |
| 1233 | template<class I, class P1, class P2, class P3, class P4, |
| 1234 | class P5, class P6, class P7, class P8> |
| 1235 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, |
| 1236 | P5 p5, P6 p6, P7 p7, P8 p8) { |
| 1237 | return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1238 | } |
| 1239 | |
| 1240 | template<class I, class P1, class P2, class P3, class P4, |
| 1241 | class P5, class P6, class P7, class P8> |
| 1242 | I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) { |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1243 | return I::cast( |
| 1244 | AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7, p8))); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1245 | } |
| 1246 | |
danno@chromium.org | ad75d6f | 2013-08-12 16:57:59 +0000 | [diff] [blame] | 1247 | void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 1248 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1249 | int position() const { return position_; } |
| 1250 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1251 | protected: |
| 1252 | virtual bool BuildGraph() = 0; |
| 1253 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1254 | HBasicBlock* CreateBasicBlock(HEnvironment* env); |
| 1255 | HBasicBlock* CreateLoopHeaderBlock(); |
| 1256 | |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1257 | HValue* BuildCheckHeapObject(HValue* object); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1258 | HValue* BuildCheckMap(HValue* obj, Handle<Map> map); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1259 | HValue* BuildWrapReceiver(HValue* object, HValue* function); |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1260 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1261 | // Building common constructs |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1262 | HValue* BuildCheckForCapacityGrow(HValue* object, |
| 1263 | HValue* elements, |
| 1264 | ElementsKind kind, |
| 1265 | HValue* length, |
| 1266 | HValue* key, |
| 1267 | bool is_js_array); |
| 1268 | |
| 1269 | HValue* BuildCopyElementsOnWrite(HValue* object, |
| 1270 | HValue* elements, |
| 1271 | ElementsKind kind, |
| 1272 | HValue* length); |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1273 | |
jkummerow@chromium.org | ba72ec8 | 2013-07-22 09:21:20 +0000 | [diff] [blame] | 1274 | void BuildTransitionElementsKind(HValue* object, |
| 1275 | HValue* map, |
| 1276 | ElementsKind from_kind, |
| 1277 | ElementsKind to_kind, |
| 1278 | bool is_jsarray); |
| 1279 | |
bmeurer@chromium.org | e7a0745 | 2013-10-21 13:27:29 +0000 | [diff] [blame] | 1280 | HValue* BuildNumberToString(HValue* object, Handle<Type> type); |
machenbach@chromium.org | 3d079fe | 2013-09-25 08:19:55 +0000 | [diff] [blame] | 1281 | |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame^] | 1282 | HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver, |
| 1283 | HValue* key); |
| 1284 | |
machenbach@chromium.org | 0cc0950 | 2013-11-13 12:20:55 +0000 | [diff] [blame] | 1285 | // Computes the size for a sequential string of the given length and encoding. |
| 1286 | HValue* BuildSeqStringSizeFor(HValue* length, |
| 1287 | String::Encoding encoding); |
| 1288 | // Copies characters from one sequential string to another. |
| 1289 | void BuildCopySeqStringChars(HValue* src, |
| 1290 | HValue* src_offset, |
| 1291 | String::Encoding src_encoding, |
| 1292 | HValue* dst, |
| 1293 | HValue* dst_offset, |
| 1294 | String::Encoding dst_encoding, |
| 1295 | HValue* length); |
| 1296 | // Both operands are non-empty strings. |
| 1297 | HValue* BuildUncheckedStringAdd(HValue* left, |
| 1298 | HValue* right, |
| 1299 | PretenureFlag pretenure_flag); |
| 1300 | // Both operands are strings. |
| 1301 | HValue* BuildStringAdd(HValue* left, |
| 1302 | HValue* right, |
| 1303 | PretenureFlag pretenure_flag); |
| 1304 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1305 | HInstruction* BuildUncheckedMonomorphicElementAccess( |
jkummerow@chromium.org | 1e8da74 | 2013-08-26 17:13:35 +0000 | [diff] [blame] | 1306 | HValue* checked_object, |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1307 | HValue* key, |
| 1308 | HValue* val, |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1309 | bool is_js_array, |
| 1310 | ElementsKind elements_kind, |
mstarzinger@chromium.org | 068ea0a | 2013-01-30 09:39:44 +0000 | [diff] [blame] | 1311 | bool is_store, |
ulan@chromium.org | 906e2fb | 2013-05-14 08:14:38 +0000 | [diff] [blame] | 1312 | LoadKeyedHoleMode load_mode, |
svenpanne@chromium.org | 53ad175 | 2013-05-27 12:20:38 +0000 | [diff] [blame] | 1313 | KeyedAccessStoreMode store_mode); |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1314 | |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 1315 | HInstruction* AddElementAccess( |
jkummerow@chromium.org | ba72ec8 | 2013-07-22 09:21:20 +0000 | [diff] [blame] | 1316 | HValue* elements, |
| 1317 | HValue* checked_key, |
| 1318 | HValue* val, |
| 1319 | HValue* dependency, |
| 1320 | ElementsKind elements_kind, |
| 1321 | bool is_store, |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 1322 | LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE); |
jkummerow@chromium.org | ba72ec8 | 2013-07-22 09:21:20 +0000 | [diff] [blame] | 1323 | |
verwaest@chromium.org | ec6855e | 2013-08-22 12:26:58 +0000 | [diff] [blame] | 1324 | HLoadNamedField* BuildLoadNamedField(HValue* object, HObjectAccess access); |
bmeurer@chromium.org | db78329 | 2013-10-23 06:51:00 +0000 | [diff] [blame] | 1325 | HInstruction* AddLoadNamedField(HValue* object, HObjectAccess access); |
verwaest@chromium.org | ec6855e | 2013-08-22 12:26:58 +0000 | [diff] [blame] | 1326 | HInstruction* BuildLoadStringLength(HValue* object, HValue* checked_value); |
machenbach@chromium.org | 0cc0950 | 2013-11-13 12:20:55 +0000 | [diff] [blame] | 1327 | HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map> map); |
| 1328 | HStoreNamedField* AddStoreMapConstantNoWriteBarrier(HValue* object, |
| 1329 | Handle<Map> map) { |
| 1330 | HStoreNamedField* store_map = AddStoreMapConstant(object, map); |
| 1331 | store_map->SkipWriteBarrier(); |
| 1332 | return store_map; |
| 1333 | } |
verwaest@chromium.org | ec6855e | 2013-08-22 12:26:58 +0000 | [diff] [blame] | 1334 | HLoadNamedField* AddLoadElements(HValue* object); |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1335 | |
| 1336 | bool MatchRotateRight(HValue* left, |
| 1337 | HValue* right, |
| 1338 | HValue** operand, |
| 1339 | HValue** shift_amount); |
| 1340 | |
| 1341 | HInstruction* BuildBinaryOperation(Token::Value op, |
| 1342 | HValue* left, |
| 1343 | HValue* right, |
| 1344 | Handle<Type> left_type, |
| 1345 | Handle<Type> right_type, |
| 1346 | Handle<Type> result_type, |
jkummerow@chromium.org | 25b0e21 | 2013-10-04 15:38:52 +0000 | [diff] [blame] | 1347 | Maybe<int> fixed_right_arg, |
| 1348 | bool binop_stub = false); |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1349 | |
machenbach@chromium.org | c1789ee | 2013-07-05 07:09:57 +0000 | [diff] [blame] | 1350 | HLoadNamedField* AddLoadFixedArrayLength(HValue *object); |
| 1351 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1352 | HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin); |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1353 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1354 | HValue* EnforceNumberType(HValue* number, Handle<Type> expected); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1355 | HValue* TruncateToNumber(HValue* value, Handle<Type>* expected); |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1356 | |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1357 | void FinishExitWithHardDeoptimization(const char* reason, |
| 1358 | HBasicBlock* continuation); |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1359 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1360 | void AddIncrementCounter(StatsCounter* counter); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1361 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1362 | class IfBuilder V8_FINAL { |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1363 | public: |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1364 | explicit IfBuilder(HGraphBuilder* builder); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1365 | IfBuilder(HGraphBuilder* builder, |
| 1366 | HIfContinuation* continuation); |
| 1367 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1368 | ~IfBuilder() { |
| 1369 | if (!finished_) End(); |
| 1370 | } |
| 1371 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1372 | template<class Condition> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1373 | Condition* If(HValue *p) { |
| 1374 | Condition* compare = builder()->New<Condition>(p); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1375 | AddCompare(compare); |
| 1376 | return compare; |
| 1377 | } |
| 1378 | |
| 1379 | template<class Condition, class P2> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1380 | Condition* If(HValue* p1, P2 p2) { |
| 1381 | Condition* compare = builder()->New<Condition>(p1, p2); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1382 | AddCompare(compare); |
| 1383 | return compare; |
| 1384 | } |
| 1385 | |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1386 | template<class Condition, class P2, class P3> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1387 | Condition* If(HValue* p1, P2 p2, P3 p3) { |
| 1388 | Condition* compare = builder()->New<Condition>(p1, p2, p3); |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1389 | AddCompare(compare); |
| 1390 | return compare; |
| 1391 | } |
| 1392 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1393 | template<class Condition> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1394 | Condition* IfNot(HValue* p) { |
| 1395 | Condition* compare = If<Condition>(p); |
| 1396 | compare->Not(); |
| 1397 | return compare; |
| 1398 | } |
| 1399 | |
| 1400 | template<class Condition, class P2> |
| 1401 | Condition* IfNot(HValue* p1, P2 p2) { |
| 1402 | Condition* compare = If<Condition>(p1, p2); |
| 1403 | compare->Not(); |
| 1404 | return compare; |
| 1405 | } |
| 1406 | |
| 1407 | template<class Condition, class P2, class P3> |
| 1408 | Condition* IfNot(HValue* p1, P2 p2, P3 p3) { |
| 1409 | Condition* compare = If<Condition>(p1, p2, p3); |
| 1410 | compare->Not(); |
| 1411 | return compare; |
| 1412 | } |
| 1413 | |
| 1414 | template<class Condition> |
| 1415 | Condition* OrIf(HValue *p) { |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1416 | Or(); |
| 1417 | return If<Condition>(p); |
| 1418 | } |
| 1419 | |
| 1420 | template<class Condition, class P2> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1421 | Condition* OrIf(HValue* p1, P2 p2) { |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1422 | Or(); |
| 1423 | return If<Condition>(p1, p2); |
| 1424 | } |
| 1425 | |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1426 | template<class Condition, class P2, class P3> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1427 | Condition* OrIf(HValue* p1, P2 p2, P3 p3) { |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1428 | Or(); |
| 1429 | return If<Condition>(p1, p2, p3); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1430 | } |
| 1431 | |
| 1432 | template<class Condition> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1433 | Condition* AndIf(HValue *p) { |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1434 | And(); |
| 1435 | return If<Condition>(p); |
| 1436 | } |
| 1437 | |
| 1438 | template<class Condition, class P2> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1439 | Condition* AndIf(HValue* p1, P2 p2) { |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1440 | And(); |
| 1441 | return If<Condition>(p1, p2); |
| 1442 | } |
| 1443 | |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1444 | template<class Condition, class P2, class P3> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1445 | Condition* AndIf(HValue* p1, P2 p2, P3 p3) { |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1446 | And(); |
| 1447 | return If<Condition>(p1, p2, p3); |
| 1448 | } |
| 1449 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1450 | void Or(); |
| 1451 | void And(); |
| 1452 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1453 | // Captures the current state of this IfBuilder in the specified |
| 1454 | // continuation and ends this IfBuilder. |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1455 | void CaptureContinuation(HIfContinuation* continuation); |
| 1456 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1457 | // Joins the specified continuation from this IfBuilder and ends this |
| 1458 | // IfBuilder. This appends a Goto instruction from the true branch of |
| 1459 | // this IfBuilder to the true branch of the continuation unless the |
| 1460 | // true branch of this IfBuilder is already finished. And vice versa |
| 1461 | // for the false branch. |
| 1462 | // |
| 1463 | // The basic idea is as follows: You have several nested IfBuilder's |
| 1464 | // that you want to join based on two possible outcomes (i.e. success |
| 1465 | // and failure, or whatever). You can do this easily using this method |
| 1466 | // now, for example: |
| 1467 | // |
| 1468 | // HIfContinuation cont(graph()->CreateBasicBlock(), |
| 1469 | // graph()->CreateBasicBlock()); |
| 1470 | // ... |
| 1471 | // IfBuilder if_whatever(this); |
| 1472 | // if_whatever.If<Condition>(arg); |
| 1473 | // if_whatever.Then(); |
| 1474 | // ... |
| 1475 | // if_whatever.Else(); |
| 1476 | // ... |
| 1477 | // if_whatever.JoinContinuation(&cont); |
| 1478 | // ... |
| 1479 | // IfBuilder if_something(this); |
| 1480 | // if_something.If<Condition>(arg1, arg2); |
| 1481 | // if_something.Then(); |
| 1482 | // ... |
| 1483 | // if_something.Else(); |
| 1484 | // ... |
| 1485 | // if_something.JoinContinuation(&cont); |
| 1486 | // ... |
| 1487 | // IfBuilder if_finally(this, &cont); |
| 1488 | // if_finally.Then(); |
| 1489 | // // continues after then code of if_whatever or if_something. |
| 1490 | // ... |
| 1491 | // if_finally.Else(); |
| 1492 | // // continues after else code of if_whatever or if_something. |
| 1493 | // ... |
| 1494 | // if_finally.End(); |
| 1495 | void JoinContinuation(HIfContinuation* continuation); |
| 1496 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1497 | void Then(); |
| 1498 | void Else(); |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1499 | void End(); |
| 1500 | |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1501 | void Deopt(const char* reason); |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame^] | 1502 | void ThenDeopt(const char* reason) { |
| 1503 | Then(); |
| 1504 | Deopt(reason); |
| 1505 | } |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1506 | void ElseDeopt(const char* reason) { |
ulan@chromium.org | 32d7dba | 2013-04-24 10:59:06 +0000 | [diff] [blame] | 1507 | Else(); |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1508 | Deopt(reason); |
ulan@chromium.org | 32d7dba | 2013-04-24 10:59:06 +0000 | [diff] [blame] | 1509 | } |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1510 | |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1511 | void Return(HValue* value); |
| 1512 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1513 | private: |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1514 | HControlInstruction* AddCompare(HControlInstruction* compare); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1515 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1516 | HGraphBuilder* builder() const { return builder_; } |
mstarzinger@chromium.org | 71fc346 | 2013-02-27 09:34:27 +0000 | [diff] [blame] | 1517 | |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame^] | 1518 | void AddMergeAtJoinBlock(bool deopt); |
| 1519 | |
| 1520 | void Finish(); |
| 1521 | void Finish(HBasicBlock** then_continuation, |
| 1522 | HBasicBlock** else_continuation); |
| 1523 | |
| 1524 | class MergeAtJoinBlock : public ZoneObject { |
| 1525 | public: |
| 1526 | MergeAtJoinBlock(HBasicBlock* block, |
| 1527 | bool deopt, |
| 1528 | MergeAtJoinBlock* next) |
| 1529 | : block_(block), |
| 1530 | deopt_(deopt), |
| 1531 | next_(next) {} |
| 1532 | HBasicBlock* block_; |
| 1533 | bool deopt_; |
| 1534 | MergeAtJoinBlock* next_; |
| 1535 | }; |
| 1536 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1537 | HGraphBuilder* builder_; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1538 | bool finished_ : 1; |
| 1539 | bool did_then_ : 1; |
| 1540 | bool did_else_ : 1; |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame^] | 1541 | bool did_else_if_ : 1; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1542 | bool did_and_ : 1; |
| 1543 | bool did_or_ : 1; |
| 1544 | bool captured_ : 1; |
| 1545 | bool needs_compare_ : 1; |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame^] | 1546 | bool pending_merge_block_ : 1; |
ulan@chromium.org | 09d7ab5 | 2013-02-25 15:50:35 +0000 | [diff] [blame] | 1547 | HBasicBlock* first_true_block_; |
ulan@chromium.org | 09d7ab5 | 2013-02-25 15:50:35 +0000 | [diff] [blame] | 1548 | HBasicBlock* first_false_block_; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1549 | HBasicBlock* split_edge_merge_block_; |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame^] | 1550 | MergeAtJoinBlock* merge_at_join_blocks_; |
| 1551 | int normal_merge_at_join_block_count_; |
| 1552 | int deopt_merge_at_join_block_count_; |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1553 | }; |
| 1554 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1555 | class LoopBuilder V8_FINAL { |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1556 | public: |
| 1557 | enum Direction { |
| 1558 | kPreIncrement, |
| 1559 | kPostIncrement, |
| 1560 | kPreDecrement, |
| 1561 | kPostDecrement |
| 1562 | }; |
| 1563 | |
| 1564 | LoopBuilder(HGraphBuilder* builder, |
| 1565 | HValue* context, |
danno@chromium.org | 2d18b36 | 2013-03-22 17:19:26 +0000 | [diff] [blame] | 1566 | Direction direction); |
verwaest@chromium.org | 662436e | 2013-08-28 08:41:27 +0000 | [diff] [blame] | 1567 | LoopBuilder(HGraphBuilder* builder, |
| 1568 | HValue* context, |
| 1569 | Direction direction, |
| 1570 | HValue* increment_amount); |
| 1571 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1572 | ~LoopBuilder() { |
| 1573 | ASSERT(finished_); |
| 1574 | } |
| 1575 | |
ulan@chromium.org | 09d7ab5 | 2013-02-25 15:50:35 +0000 | [diff] [blame] | 1576 | HValue* BeginBody( |
| 1577 | HValue* initial, |
| 1578 | HValue* terminating, |
ulan@chromium.org | dfe5307 | 2013-06-06 14:14:51 +0000 | [diff] [blame] | 1579 | Token::Value token); |
verwaest@chromium.org | 662436e | 2013-08-28 08:41:27 +0000 | [diff] [blame] | 1580 | |
| 1581 | void Break(); |
| 1582 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1583 | void EndBody(); |
| 1584 | |
| 1585 | private: |
mstarzinger@chromium.org | 71fc346 | 2013-02-27 09:34:27 +0000 | [diff] [blame] | 1586 | Zone* zone() { return builder_->zone(); } |
| 1587 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1588 | HGraphBuilder* builder_; |
| 1589 | HValue* context_; |
verwaest@chromium.org | 662436e | 2013-08-28 08:41:27 +0000 | [diff] [blame] | 1590 | HValue* increment_amount_; |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1591 | HInstruction* increment_; |
| 1592 | HPhi* phi_; |
| 1593 | HBasicBlock* header_block_; |
| 1594 | HBasicBlock* body_block_; |
| 1595 | HBasicBlock* exit_block_; |
verwaest@chromium.org | 662436e | 2013-08-28 08:41:27 +0000 | [diff] [blame] | 1596 | HBasicBlock* exit_trampoline_block_; |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1597 | Direction direction_; |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1598 | bool finished_; |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1599 | }; |
| 1600 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1601 | HValue* BuildNewElementsCapacity(HValue* old_capacity); |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1602 | |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1603 | void BuildNewSpaceArrayCheck(HValue* length, |
| 1604 | ElementsKind kind); |
| 1605 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1606 | class JSArrayBuilder V8_FINAL { |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1607 | public: |
| 1608 | JSArrayBuilder(HGraphBuilder* builder, |
| 1609 | ElementsKind kind, |
| 1610 | HValue* allocation_site_payload, |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1611 | HValue* constructor_function, |
| 1612 | AllocationSiteOverrideMode override_mode); |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 1613 | |
| 1614 | JSArrayBuilder(HGraphBuilder* builder, |
| 1615 | ElementsKind kind, |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame^] | 1616 | HValue* constructor_function = NULL); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1617 | |
machenbach@chromium.org | b5be0a9 | 2013-11-15 10:32:41 +0000 | [diff] [blame] | 1618 | enum FillMode { |
| 1619 | DONT_FILL_WITH_HOLE, |
| 1620 | FILL_WITH_HOLE |
| 1621 | }; |
| 1622 | |
| 1623 | ElementsKind kind() { return kind_; } |
| 1624 | |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1625 | HValue* AllocateEmptyArray(); |
| 1626 | HValue* AllocateArray(HValue* capacity, HValue* length_field, |
machenbach@chromium.org | b5be0a9 | 2013-11-15 10:32:41 +0000 | [diff] [blame] | 1627 | FillMode fill_mode = FILL_WITH_HOLE); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1628 | HValue* GetElementsLocation() { return elements_location_; } |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame^] | 1629 | HValue* EmitMapCode(); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1630 | |
| 1631 | private: |
| 1632 | Zone* zone() const { return builder_->zone(); } |
| 1633 | int elements_size() const { |
| 1634 | return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize; |
| 1635 | } |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1636 | HGraphBuilder* builder() { return builder_; } |
| 1637 | HGraph* graph() { return builder_->graph(); } |
| 1638 | int initial_capacity() { |
| 1639 | STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0); |
| 1640 | return JSArray::kPreallocatedArrayElements; |
| 1641 | } |
| 1642 | |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 1643 | HValue* EmitInternalMapCode(); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1644 | HValue* EstablishEmptyArrayAllocationSize(); |
| 1645 | HValue* EstablishAllocationSize(HValue* length_node); |
| 1646 | HValue* AllocateArray(HValue* size_in_bytes, HValue* capacity, |
machenbach@chromium.org | b5be0a9 | 2013-11-15 10:32:41 +0000 | [diff] [blame] | 1647 | HValue* length_field, |
| 1648 | FillMode fill_mode = FILL_WITH_HOLE); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1649 | |
| 1650 | HGraphBuilder* builder_; |
| 1651 | ElementsKind kind_; |
| 1652 | AllocationSiteMode mode_; |
| 1653 | HValue* allocation_site_payload_; |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 1654 | HValue* constructor_function_; |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1655 | HInnerAllocatedObject* elements_location_; |
| 1656 | }; |
| 1657 | |
machenbach@chromium.org | b5be0a9 | 2013-11-15 10:32:41 +0000 | [diff] [blame] | 1658 | HValue* BuildAllocateArrayFromLength(JSArrayBuilder* array_builder, |
| 1659 | HValue* length_argument); |
| 1660 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1661 | HValue* BuildAllocateElements(ElementsKind kind, |
danno@chromium.org | 2d18b36 | 2013-03-22 17:19:26 +0000 | [diff] [blame] | 1662 | HValue* capacity); |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1663 | |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 1664 | void BuildInitializeElementsHeader(HValue* elements, |
| 1665 | ElementsKind kind, |
| 1666 | HValue* capacity); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 1667 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1668 | HValue* BuildAllocateElementsAndInitializeElementsHeader(ElementsKind kind, |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 1669 | HValue* capacity); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 1670 | |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1671 | // array must have been allocated with enough room for |
jkummerow@chromium.org | ba72ec8 | 2013-07-22 09:21:20 +0000 | [diff] [blame] | 1672 | // 1) the JSArray, 2) a AllocationMemento if mode requires it, |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1673 | // 3) a FixedArray or FixedDoubleArray. |
| 1674 | // A pointer to the Fixed(Double)Array is returned. |
| 1675 | HInnerAllocatedObject* BuildJSArrayHeader(HValue* array, |
| 1676 | HValue* array_map, |
| 1677 | AllocationSiteMode mode, |
jkummerow@chromium.org | fb732b1 | 2013-07-26 10:27:09 +0000 | [diff] [blame] | 1678 | ElementsKind elements_kind, |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1679 | HValue* allocation_site_payload, |
| 1680 | HValue* length_field); |
| 1681 | |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1682 | HValue* BuildGrowElementsCapacity(HValue* object, |
| 1683 | HValue* elements, |
| 1684 | ElementsKind kind, |
danno@chromium.org | bee5199 | 2013-07-10 14:57:15 +0000 | [diff] [blame] | 1685 | ElementsKind new_kind, |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1686 | HValue* length, |
danno@chromium.org | 2d18b36 | 2013-03-22 17:19:26 +0000 | [diff] [blame] | 1687 | HValue* new_capacity); |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1688 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1689 | void BuildFillElementsWithHole(HValue* elements, |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1690 | ElementsKind elements_kind, |
| 1691 | HValue* from, |
danno@chromium.org | 2d18b36 | 2013-03-22 17:19:26 +0000 | [diff] [blame] | 1692 | HValue* to); |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1693 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1694 | void BuildCopyElements(HValue* from_elements, |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1695 | ElementsKind from_elements_kind, |
| 1696 | HValue* to_elements, |
| 1697 | ElementsKind to_elements_kind, |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1698 | HValue* length, |
danno@chromium.org | 2d18b36 | 2013-03-22 17:19:26 +0000 | [diff] [blame] | 1699 | HValue* capacity); |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1700 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1701 | HValue* BuildCloneShallowArray(HValue* boilerplate, |
danno@chromium.org | bee5199 | 2013-07-10 14:57:15 +0000 | [diff] [blame] | 1702 | HValue* allocation_site, |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 1703 | AllocationSiteMode mode, |
| 1704 | ElementsKind kind, |
| 1705 | int length); |
| 1706 | |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame^] | 1707 | HValue* BuildElementIndexHash(HValue* index); |
| 1708 | |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1709 | void BuildCompareNil( |
| 1710 | HValue* value, |
danno@chromium.org | 4172848 | 2013-06-12 22:31:22 +0000 | [diff] [blame] | 1711 | Handle<Type> type, |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1712 | HIfContinuation* continuation); |
| 1713 | |
jkummerow@chromium.org | ba72ec8 | 2013-07-22 09:21:20 +0000 | [diff] [blame] | 1714 | HValue* BuildCreateAllocationMemento(HValue* previous_object, |
| 1715 | int previous_object_size, |
| 1716 | HValue* payload); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1717 | |
verwaest@chromium.org | ec6855e | 2013-08-22 12:26:58 +0000 | [diff] [blame] | 1718 | HInstruction* BuildConstantMapCheck(Handle<JSObject> constant, |
| 1719 | CompilationInfo* info); |
| 1720 | HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype, |
| 1721 | Handle<JSObject> holder); |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1722 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1723 | HInstruction* BuildGetNativeContext(); |
| 1724 | HInstruction* BuildGetArrayFunction(); |
ulan@chromium.org | 57ff881 | 2013-05-10 08:16:55 +0000 | [diff] [blame] | 1725 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1726 | protected: |
| 1727 | void SetSourcePosition(int position) { |
| 1728 | ASSERT(position != RelocInfo::kNoPosition); |
| 1729 | position_ = position; |
| 1730 | } |
| 1731 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1732 | private: |
| 1733 | HGraphBuilder(); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1734 | |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame^] | 1735 | HValue* BuildUncheckedDictionaryElementLoadHelper( |
| 1736 | HValue* elements, |
| 1737 | HValue* key, |
| 1738 | HValue* hash, |
| 1739 | HValue* mask, |
| 1740 | int current_probe); |
| 1741 | |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1742 | void PadEnvironmentForContinuation(HBasicBlock* from, |
| 1743 | HBasicBlock* continuation); |
| 1744 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1745 | CompilationInfo* info_; |
| 1746 | HGraph* graph_; |
| 1747 | HBasicBlock* current_block_; |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1748 | int position_; |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1749 | }; |
| 1750 | |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1751 | |
| 1752 | template<> |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1753 | inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>( |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1754 | const char* reason, Deoptimizer::BailoutType type) { |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1755 | if (type == Deoptimizer::SOFT) { |
| 1756 | isolate()->counters()->soft_deopts_requested()->Increment(); |
| 1757 | if (FLAG_always_opt) return NULL; |
| 1758 | } |
| 1759 | if (current_block()->IsDeoptimizing()) return NULL; |
jkummerow@chromium.org | d8a3a14 | 2013-10-03 12:15:05 +0000 | [diff] [blame] | 1760 | HBasicBlock* after_deopt_block = CreateBasicBlock( |
| 1761 | current_block()->last_environment()); |
| 1762 | HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1763 | if (type == Deoptimizer::SOFT) { |
| 1764 | isolate()->counters()->soft_deopts_inserted()->Increment(); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1765 | } |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1766 | FinishCurrentBlock(instr); |
jkummerow@chromium.org | d8a3a14 | 2013-10-03 12:15:05 +0000 | [diff] [blame] | 1767 | set_current_block(after_deopt_block); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1768 | return instr; |
| 1769 | } |
| 1770 | |
| 1771 | |
| 1772 | template<> |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1773 | inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>( |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1774 | const char* reason, Deoptimizer::BailoutType type) { |
| 1775 | return static_cast<HDeoptimize*>(AddUncasted<HDeoptimize>(reason, type)); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1776 | } |
| 1777 | |
| 1778 | |
| 1779 | template<> |
| 1780 | inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>( |
| 1781 | BailoutId id, |
| 1782 | RemovableSimulate removable) { |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1783 | HSimulate* instr = current_block()->CreateSimulate(id, removable); |
| 1784 | AddInstruction(instr); |
| 1785 | return instr; |
| 1786 | } |
| 1787 | |
| 1788 | |
| 1789 | template<> |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1790 | inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) { |
| 1791 | return AddUncasted<HSimulate>(id, FIXED_SIMULATE); |
| 1792 | } |
| 1793 | |
| 1794 | |
| 1795 | template<> |
| 1796 | inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) { |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1797 | int num_parameters = graph()->info()->num_parameters(); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1798 | HValue* params = AddUncasted<HConstant>(num_parameters); |
| 1799 | HReturn* return_instruction = New<HReturn>(value, params); |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1800 | FinishExitCurrentBlock(return_instruction); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1801 | return return_instruction; |
| 1802 | } |
| 1803 | |
| 1804 | |
| 1805 | template<> |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1806 | inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) { |
| 1807 | return AddUncasted<HReturn>(static_cast<HValue*>(value)); |
| 1808 | } |
| 1809 | |
| 1810 | |
| 1811 | template<> |
jkummerow@chromium.org | fb7a7c4 | 2013-10-02 11:41:02 +0000 | [diff] [blame] | 1812 | inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>( |
| 1813 | Handle<String> name, |
| 1814 | const Runtime::Function* c_function, |
| 1815 | int argument_count) { |
| 1816 | HCallRuntime* instr = New<HCallRuntime>(name, c_function, argument_count); |
| 1817 | if (graph()->info()->IsStub()) { |
| 1818 | // When compiling code stubs, we don't want to save all double registers |
| 1819 | // upon entry to the stub, but instead have the call runtime instruction |
| 1820 | // save the double registers only on-demand (in the fallback case). |
| 1821 | instr->set_save_doubles(kSaveFPRegs); |
| 1822 | } |
| 1823 | AddInstruction(instr); |
| 1824 | return instr; |
| 1825 | } |
| 1826 | |
| 1827 | |
| 1828 | template<> |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1829 | inline HInstruction* HGraphBuilder::NewUncasted<HContext>() { |
| 1830 | return HContext::New(zone()); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1831 | } |
| 1832 | |
| 1833 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1834 | class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1835 | public: |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1836 | // A class encapsulating (lazily-allocated) break and continue blocks for |
| 1837 | // a breakable statement. Separated from BreakAndContinueScope so that it |
| 1838 | // can have a separate lifetime. |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1839 | class BreakAndContinueInfo V8_FINAL BASE_EMBEDDED { |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1840 | public: |
kmillikin@chromium.org | be6bd10 | 2012-02-23 08:45:21 +0000 | [diff] [blame] | 1841 | explicit BreakAndContinueInfo(BreakableStatement* target, |
| 1842 | int drop_extra = 0) |
| 1843 | : target_(target), |
| 1844 | break_block_(NULL), |
| 1845 | continue_block_(NULL), |
| 1846 | drop_extra_(drop_extra) { |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1847 | } |
| 1848 | |
| 1849 | BreakableStatement* target() { return target_; } |
| 1850 | HBasicBlock* break_block() { return break_block_; } |
| 1851 | void set_break_block(HBasicBlock* block) { break_block_ = block; } |
| 1852 | HBasicBlock* continue_block() { return continue_block_; } |
| 1853 | void set_continue_block(HBasicBlock* block) { continue_block_ = block; } |
kmillikin@chromium.org | be6bd10 | 2012-02-23 08:45:21 +0000 | [diff] [blame] | 1854 | int drop_extra() { return drop_extra_; } |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1855 | |
| 1856 | private: |
| 1857 | BreakableStatement* target_; |
| 1858 | HBasicBlock* break_block_; |
| 1859 | HBasicBlock* continue_block_; |
kmillikin@chromium.org | be6bd10 | 2012-02-23 08:45:21 +0000 | [diff] [blame] | 1860 | int drop_extra_; |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1861 | }; |
| 1862 | |
| 1863 | // A helper class to maintain a stack of current BreakAndContinueInfo |
| 1864 | // structures mirroring BreakableStatement nesting. |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1865 | class BreakAndContinueScope V8_FINAL BASE_EMBEDDED { |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1866 | public: |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1867 | BreakAndContinueScope(BreakAndContinueInfo* info, |
| 1868 | HOptimizedGraphBuilder* owner) |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1869 | : info_(info), owner_(owner), next_(owner->break_scope()) { |
| 1870 | owner->set_break_scope(this); |
| 1871 | } |
| 1872 | |
| 1873 | ~BreakAndContinueScope() { owner_->set_break_scope(next_); } |
| 1874 | |
| 1875 | BreakAndContinueInfo* info() { return info_; } |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1876 | HOptimizedGraphBuilder* owner() { return owner_; } |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1877 | BreakAndContinueScope* next() { return next_; } |
| 1878 | |
| 1879 | // Search the break stack for a break or continue target. |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 1880 | enum BreakType { BREAK, CONTINUE }; |
kmillikin@chromium.org | be6bd10 | 2012-02-23 08:45:21 +0000 | [diff] [blame] | 1881 | HBasicBlock* Get(BreakableStatement* stmt, BreakType type, int* drop_extra); |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1882 | |
| 1883 | private: |
| 1884 | BreakAndContinueInfo* info_; |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1885 | HOptimizedGraphBuilder* owner_; |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1886 | BreakAndContinueScope* next_; |
| 1887 | }; |
| 1888 | |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 1889 | explicit HOptimizedGraphBuilder(CompilationInfo* info); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1890 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1891 | virtual bool BuildGraph() V8_OVERRIDE; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1892 | |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 1893 | // Simple accessors. |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1894 | BreakAndContinueScope* break_scope() const { return break_scope_; } |
| 1895 | void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; } |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 1896 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 1897 | bool inline_bailout() { return inline_bailout_; } |
| 1898 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1899 | HValue* context() { return environment()->context(); } |
| 1900 | |
jkummerow@chromium.org | c366976 | 2013-09-30 13:42:25 +0000 | [diff] [blame] | 1901 | HOsrBuilder* osr() const { return osr_; } |
| 1902 | |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1903 | void Bailout(BailoutReason reason); |
sgjesse@chromium.org | 8e8294a | 2011-05-02 14:30:53 +0000 | [diff] [blame] | 1904 | |
ricow@chromium.org | 4f693d6 | 2011-07-04 14:01:31 +0000 | [diff] [blame] | 1905 | HBasicBlock* CreateJoin(HBasicBlock* first, |
| 1906 | HBasicBlock* second, |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 1907 | BailoutId join_id); |
ricow@chromium.org | 4f693d6 | 2011-07-04 14:01:31 +0000 | [diff] [blame] | 1908 | |
erik.corry@gmail.com | 394dbcf | 2011-10-27 07:38:48 +0000 | [diff] [blame] | 1909 | FunctionState* function_state() const { return function_state_; } |
| 1910 | |
yangguo@chromium.org | 5645471 | 2012-02-16 15:33:53 +0000 | [diff] [blame] | 1911 | void VisitDeclarations(ZoneList<Declaration*>* declarations); |
| 1912 | |
verwaest@chromium.org | 178fb15 | 2012-07-18 11:21:48 +0000 | [diff] [blame] | 1913 | void* operator new(size_t size, Zone* zone) { |
| 1914 | return zone->New(static_cast<int>(size)); |
| 1915 | } |
yangguo@chromium.org | 304cc33 | 2012-07-24 07:59:48 +0000 | [diff] [blame] | 1916 | void operator delete(void* pointer, Zone* zone) { } |
| 1917 | void operator delete(void* pointer) { } |
verwaest@chromium.org | 178fb15 | 2012-07-18 11:21:48 +0000 | [diff] [blame] | 1918 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1919 | DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
| 1920 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1921 | protected: |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1922 | // Type of a member function that generates inline code for a native function. |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1923 | typedef void (HOptimizedGraphBuilder::*InlineFunctionGenerator) |
| 1924 | (CallRuntime* call); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1925 | |
| 1926 | // Forward declarations for inner scope classes. |
| 1927 | class SubgraphScope; |
| 1928 | |
| 1929 | static const InlineFunctionGenerator kInlineFunctionGenerators[]; |
| 1930 | |
| 1931 | static const int kMaxCallPolymorphism = 4; |
| 1932 | static const int kMaxLoadPolymorphism = 4; |
| 1933 | static const int kMaxStorePolymorphism = 4; |
| 1934 | |
danno@chromium.org | fa458e4 | 2012-02-01 10:48:36 +0000 | [diff] [blame] | 1935 | // Even in the 'unlimited' case we have to have some limit in order not to |
| 1936 | // overflow the stack. |
mstarzinger@chromium.org | 88d326b | 2012-04-23 12:57:22 +0000 | [diff] [blame] | 1937 | static const int kUnlimitedMaxInlinedSourceSize = 100000; |
| 1938 | static const int kUnlimitedMaxInlinedNodes = 10000; |
| 1939 | static const int kUnlimitedMaxInlinedNodesCumulative = 10000; |
danno@chromium.org | fa458e4 | 2012-02-01 10:48:36 +0000 | [diff] [blame] | 1940 | |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 1941 | // Maximum depth and total number of elements and properties for literal |
| 1942 | // graphs to be considered for fast deep-copying. |
| 1943 | static const int kMaxFastLiteralDepth = 3; |
| 1944 | static const int kMaxFastLiteralProperties = 8; |
| 1945 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1946 | // Simple accessors. |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 1947 | void set_function_state(FunctionState* state) { function_state_ = state; } |
| 1948 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1949 | AstContext* ast_context() const { return ast_context_; } |
| 1950 | void set_ast_context(AstContext* context) { ast_context_ = context; } |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 1951 | |
| 1952 | // Accessors forwarded to the function state. |
danno@chromium.org | 4172848 | 2013-06-12 22:31:22 +0000 | [diff] [blame] | 1953 | CompilationInfo* current_info() const { |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 1954 | return function_state()->compilation_info(); |
| 1955 | } |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 1956 | AstContext* call_context() const { |
| 1957 | return function_state()->call_context(); |
| 1958 | } |
| 1959 | HBasicBlock* function_return() const { |
| 1960 | return function_state()->function_return(); |
| 1961 | } |
| 1962 | TestContext* inlined_test_context() const { |
| 1963 | return function_state()->test_context(); |
| 1964 | } |
| 1965 | void ClearInlinedTestContext() { |
| 1966 | function_state()->ClearInlinedTestContext(); |
| 1967 | } |
erik.corry@gmail.com | 394dbcf | 2011-10-27 07:38:48 +0000 | [diff] [blame] | 1968 | StrictModeFlag function_strict_mode_flag() { |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 1969 | return function_state()->compilation_info()->is_classic_mode() |
| 1970 | ? kNonStrictMode : kStrictMode; |
karlklose@chromium.org | 44bc708 | 2011-04-11 12:33:05 +0000 | [diff] [blame] | 1971 | } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1972 | |
| 1973 | // Generators for inline runtime functions. |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 1974 | #define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \ |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1975 | void Generate##Name(CallRuntime* call); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1976 | |
| 1977 | INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION) |
| 1978 | INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION) |
| 1979 | #undef INLINE_FUNCTION_GENERATOR_DECLARATION |
| 1980 | |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 1981 | void VisitDelete(UnaryOperation* expr); |
| 1982 | void VisitVoid(UnaryOperation* expr); |
| 1983 | void VisitTypeof(UnaryOperation* expr); |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 1984 | void VisitNot(UnaryOperation* expr); |
| 1985 | |
| 1986 | void VisitComma(BinaryOperation* expr); |
erik.corry@gmail.com | d6076d9 | 2011-06-06 09:39:18 +0000 | [diff] [blame] | 1987 | void VisitLogicalExpression(BinaryOperation* expr); |
| 1988 | void VisitArithmeticExpression(BinaryOperation* expr); |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 1989 | |
rossberg@chromium.org | 2c067b1 | 2012-03-19 11:01:52 +0000 | [diff] [blame] | 1990 | bool PreProcessOsrEntry(IterationStatement* statement); |
jkummerow@chromium.org | ddda9e8 | 2011-07-06 11:27:02 +0000 | [diff] [blame] | 1991 | void VisitLoopBody(IterationStatement* stmt, |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 1992 | HBasicBlock* loop_entry, |
| 1993 | BreakAndContinueInfo* break_info); |
vegorov@chromium.org | 5d6c1f5 | 2011-02-28 13:13:38 +0000 | [diff] [blame] | 1994 | |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 1995 | // Create a back edge in the flow graph. body_exit is the predecessor |
| 1996 | // block and loop_entry is the successor block. loop_successor is the |
| 1997 | // block where control flow exits the loop normally (e.g., via failure of |
| 1998 | // the condition) and break_block is the block where control flow breaks |
| 1999 | // from the loop. All blocks except loop_entry can be NULL. The return |
| 2000 | // value is the new successor block which is the join of loop_successor |
| 2001 | // and break_block, or NULL. |
| 2002 | HBasicBlock* CreateLoop(IterationStatement* statement, |
| 2003 | HBasicBlock* loop_entry, |
| 2004 | HBasicBlock* body_exit, |
| 2005 | HBasicBlock* loop_successor, |
| 2006 | HBasicBlock* break_block); |
| 2007 | |
jkummerow@chromium.org | c366976 | 2013-09-30 13:42:25 +0000 | [diff] [blame] | 2008 | // Build a loop entry |
| 2009 | HBasicBlock* BuildLoopEntry(); |
| 2010 | |
| 2011 | // Builds a loop entry respectful of OSR requirements |
| 2012 | HBasicBlock* BuildLoopEntry(IterationStatement* statement); |
| 2013 | |
vegorov@chromium.org | 5d6c1f5 | 2011-02-28 13:13:38 +0000 | [diff] [blame] | 2014 | HBasicBlock* JoinContinue(IterationStatement* statement, |
| 2015 | HBasicBlock* exit_block, |
| 2016 | HBasicBlock* continue_block); |
| 2017 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2018 | HValue* Top() const { return environment()->Top(); } |
| 2019 | void Drop(int n) { environment()->Drop(n); } |
| 2020 | void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); } |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 2021 | bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var, |
| 2022 | int index, |
| 2023 | HValue* value, |
| 2024 | HEnvironment* env) { |
| 2025 | if (!FLAG_analyze_environment_liveness) return false; |
| 2026 | // |this| and |arguments| are always live; zapping parameters isn't |
| 2027 | // safe because function.arguments can inspect them at any time. |
| 2028 | return !var->is_this() && |
| 2029 | !var->is_arguments() && |
| 2030 | !value->IsArgumentsObject() && |
| 2031 | env->is_local_index(index); |
| 2032 | } |
| 2033 | void BindIfLive(Variable* var, HValue* value) { |
| 2034 | HEnvironment* env = environment(); |
| 2035 | int index = env->IndexFor(var); |
| 2036 | env->Bind(index, value); |
| 2037 | if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { |
| 2038 | HEnvironmentMarker* bind = |
bmeurer@chromium.org | db78329 | 2013-10-23 06:51:00 +0000 | [diff] [blame] | 2039 | Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index); |
| 2040 | USE(bind); |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 2041 | #ifdef DEBUG |
| 2042 | bind->set_closure(env->closure()); |
| 2043 | #endif |
| 2044 | } |
| 2045 | } |
bmeurer@chromium.org | db78329 | 2013-10-23 06:51:00 +0000 | [diff] [blame] | 2046 | |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 2047 | HValue* LookupAndMakeLive(Variable* var) { |
| 2048 | HEnvironment* env = environment(); |
| 2049 | int index = env->IndexFor(var); |
| 2050 | HValue* value = env->Lookup(index); |
| 2051 | if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { |
| 2052 | HEnvironmentMarker* lookup = |
bmeurer@chromium.org | db78329 | 2013-10-23 06:51:00 +0000 | [diff] [blame] | 2053 | Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index); |
| 2054 | USE(lookup); |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 2055 | #ifdef DEBUG |
| 2056 | lookup->set_closure(env->closure()); |
| 2057 | #endif |
| 2058 | } |
| 2059 | return value; |
| 2060 | } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2061 | |
sgjesse@chromium.org | 8e8294a | 2011-05-02 14:30:53 +0000 | [diff] [blame] | 2062 | // The value of the arguments object is allowed in some but not most value |
| 2063 | // contexts. (It's allowed in all effect contexts and disallowed in all |
| 2064 | // test contexts.) |
| 2065 | void VisitForValue(Expression* expr, |
| 2066 | ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED); |
kmillikin@chromium.org | c36ce6e | 2011-04-04 08:25:31 +0000 | [diff] [blame] | 2067 | void VisitForTypeOf(Expression* expr); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2068 | void VisitForEffect(Expression* expr); |
| 2069 | void VisitForControl(Expression* expr, |
| 2070 | HBasicBlock* true_block, |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 2071 | HBasicBlock* false_block); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2072 | |
verwaest@chromium.org | 753aee4 | 2012-07-17 16:15:42 +0000 | [diff] [blame] | 2073 | // Visit an argument subexpression and emit a push to the outgoing arguments. |
| 2074 | void VisitArgument(Expression* expr); |
vegorov@chromium.org | 3cf4731 | 2011-06-29 13:20:01 +0000 | [diff] [blame] | 2075 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2076 | void VisitArgumentList(ZoneList<Expression*>* arguments); |
| 2077 | |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 2078 | // Visit a list of expressions from left to right, each in a value context. |
| 2079 | void VisitExpressions(ZoneList<Expression*>* exprs); |
| 2080 | |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 2081 | // Remove the arguments from the bailout environment and emit instructions |
| 2082 | // to push them as outgoing parameters. |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 2083 | template <class Instruction> HInstruction* PreProcessCall(Instruction* call); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2084 | |
erik.corry@gmail.com | f2038fb | 2012-01-16 11:42:08 +0000 | [diff] [blame] | 2085 | void SetUpScope(Scope* scope); |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2086 | virtual void VisitStatements(ZoneList<Statement*>* statements) V8_OVERRIDE; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2087 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2088 | #define DECLARE_VISIT(type) virtual void Visit##type(type* node) V8_OVERRIDE; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2089 | AST_NODE_LIST(DECLARE_VISIT) |
| 2090 | #undef DECLARE_VISIT |
| 2091 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 2092 | private: |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2093 | // Helpers for flow graph construction. |
kmillikin@chromium.org | c36ce6e | 2011-04-04 08:25:31 +0000 | [diff] [blame] | 2094 | enum GlobalPropertyAccess { |
| 2095 | kUseCell, |
| 2096 | kUseGeneric |
| 2097 | }; |
| 2098 | GlobalPropertyAccess LookupGlobalProperty(Variable* var, |
| 2099 | LookupResult* lookup, |
| 2100 | bool is_store); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2101 | |
jkummerow@chromium.org | 28faa98 | 2012-04-13 09:58:30 +0000 | [diff] [blame] | 2102 | void EnsureArgumentsArePushedForAccess(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2103 | bool TryArgumentsAccess(Property* expr); |
whesse@chromium.org | 4acdc2c | 2011-08-15 13:01:23 +0000 | [diff] [blame] | 2104 | |
| 2105 | // Try to optimize fun.apply(receiver, arguments) pattern. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2106 | bool TryCallApply(Call* expr); |
whesse@chromium.org | 4acdc2c | 2011-08-15 13:01:23 +0000 | [diff] [blame] | 2107 | |
jkummerow@chromium.org | 212d964 | 2012-05-11 15:02:09 +0000 | [diff] [blame] | 2108 | int InliningAstSize(Handle<JSFunction> target); |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 2109 | bool TryInline(CallKind call_kind, |
| 2110 | Handle<JSFunction> target, |
yangguo@chromium.org | 304cc33 | 2012-07-24 07:59:48 +0000 | [diff] [blame] | 2111 | int arguments_count, |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 2112 | HValue* implicit_return_value, |
| 2113 | BailoutId ast_id, |
| 2114 | BailoutId return_id, |
| 2115 | InliningKind inlining_kind); |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 2116 | |
| 2117 | bool TryInlineCall(Call* expr, bool drop_extra = false); |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 2118 | bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value); |
jkummerow@chromium.org | 3d00d0a | 2013-09-04 13:57:32 +0000 | [diff] [blame] | 2119 | bool TryInlineGetter(Handle<JSFunction> getter, |
| 2120 | BailoutId ast_id, |
| 2121 | BailoutId return_id); |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 2122 | bool TryInlineSetter(Handle<JSFunction> setter, |
danno@chromium.org | b0deb65 | 2013-06-20 16:20:19 +0000 | [diff] [blame] | 2123 | BailoutId id, |
| 2124 | BailoutId assignment_id, |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 2125 | HValue* implicit_return_value); |
ulan@chromium.org | 6ba1fd0 | 2013-02-14 14:56:11 +0000 | [diff] [blame] | 2126 | bool TryInlineApply(Handle<JSFunction> function, |
| 2127 | Call* expr, |
| 2128 | int arguments_count); |
yangguo@chromium.org | 78d1ad4 | 2012-02-09 13:53:47 +0000 | [diff] [blame] | 2129 | bool TryInlineBuiltinMethodCall(Call* expr, |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 2130 | HValue* receiver, |
| 2131 | Handle<Map> receiver_map, |
| 2132 | CheckType check_type); |
yangguo@chromium.org | 78d1ad4 | 2012-02-09 13:53:47 +0000 | [diff] [blame] | 2133 | bool TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra); |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2134 | |
| 2135 | // If --trace-inlining, print a line of the inlining trace. Inlining |
| 2136 | // succeeded if the reason string is NULL and failed if there is a |
| 2137 | // non-NULL reason string. |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 2138 | void TraceInline(Handle<JSFunction> target, |
| 2139 | Handle<JSFunction> caller, |
| 2140 | const char* failure_reason); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2141 | |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 2142 | void HandleGlobalVariableAssignment(Variable* var, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2143 | HValue* value, |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 2144 | BailoutId ast_id); |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 2145 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2146 | void HandlePropertyAssignment(Assignment* expr); |
| 2147 | void HandleCompoundAssignment(Assignment* expr); |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 2148 | void HandlePolymorphicLoadNamedField(BailoutId ast_id, |
jkummerow@chromium.org | 3d00d0a | 2013-09-04 13:57:32 +0000 | [diff] [blame] | 2149 | BailoutId return_id, |
jkummerow@chromium.org | 1456e70 | 2012-03-30 08:38:13 +0000 | [diff] [blame] | 2150 | HValue* object, |
| 2151 | SmallMapList* types, |
| 2152 | Handle<String> name); |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 2153 | |
machenbach@chromium.org | b5be0a9 | 2013-11-15 10:32:41 +0000 | [diff] [blame] | 2154 | bool IsCallNewArrayInlineable(CallNew* expr); |
| 2155 | void BuildInlinedCallNewArray(CallNew* expr); |
| 2156 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 2157 | class PropertyAccessInfo { |
| 2158 | public: |
| 2159 | PropertyAccessInfo(Isolate* isolate, Handle<Map> map, Handle<String> name) |
| 2160 | : lookup_(isolate), |
| 2161 | map_(map), |
| 2162 | name_(name), |
| 2163 | access_(HObjectAccess::ForMap()) { } |
| 2164 | |
| 2165 | // Checkes whether this PropertyAccessInfo can be handled as a monomorphic |
| 2166 | // load named. It additionally fills in the fields necessary to generate the |
| 2167 | // lookup code. |
| 2168 | bool CanLoadMonomorphic(); |
| 2169 | |
| 2170 | // Checks whether all types behave uniform when loading name. If all maps |
| 2171 | // behave the same, a single monomorphic load instruction can be emitted, |
| 2172 | // guarded by a single map-checks instruction that whether the receiver is |
| 2173 | // an instance of any of the types. |
| 2174 | // This method skips the first type in types, assuming that this |
| 2175 | // PropertyAccessInfo is built for types->first(). |
| 2176 | bool CanLoadAsMonomorphic(SmallMapList* types); |
| 2177 | |
machenbach@chromium.org | 8e36b5b | 2013-09-26 07:36:30 +0000 | [diff] [blame] | 2178 | bool IsJSObjectFieldAccessor() { |
| 2179 | int offset; // unused |
| 2180 | return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset); |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 2181 | } |
| 2182 | |
machenbach@chromium.org | 8e36b5b | 2013-09-26 07:36:30 +0000 | [diff] [blame] | 2183 | bool GetJSObjectFieldAccess(HObjectAccess* access) { |
| 2184 | if (IsStringLength()) { |
| 2185 | *access = HObjectAccess::ForStringLength(); |
| 2186 | return true; |
| 2187 | } else if (IsArrayLength()) { |
| 2188 | *access = HObjectAccess::ForArrayLength(map_->elements_kind()); |
| 2189 | return true; |
| 2190 | } else { |
| 2191 | int offset; |
| 2192 | if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) { |
| 2193 | *access = HObjectAccess::ForJSObjectOffset(offset); |
| 2194 | return true; |
| 2195 | } |
| 2196 | return false; |
| 2197 | } |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 2198 | } |
| 2199 | |
| 2200 | bool has_holder() { return !holder_.is_null(); } |
| 2201 | |
| 2202 | LookupResult* lookup() { return &lookup_; } |
| 2203 | Handle<Map> map() { return map_; } |
| 2204 | Handle<JSObject> holder() { return holder_; } |
| 2205 | Handle<JSFunction> accessor() { return accessor_; } |
| 2206 | Handle<Object> constant() { return constant_; } |
| 2207 | HObjectAccess access() { return access_; } |
| 2208 | |
| 2209 | private: |
| 2210 | Isolate* isolate() { return lookup_.isolate(); } |
| 2211 | |
machenbach@chromium.org | 8e36b5b | 2013-09-26 07:36:30 +0000 | [diff] [blame] | 2212 | bool IsStringLength() { |
| 2213 | return map_->instance_type() < FIRST_NONSTRING_TYPE && |
| 2214 | name_->Equals(isolate()->heap()->length_string()); |
| 2215 | } |
| 2216 | |
| 2217 | bool IsArrayLength() { |
| 2218 | return map_->instance_type() == JS_ARRAY_TYPE && |
| 2219 | name_->Equals(isolate()->heap()->length_string()); |
| 2220 | } |
| 2221 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 2222 | bool LoadResult(Handle<Map> map); |
| 2223 | bool LookupDescriptor(); |
| 2224 | bool LookupInPrototypes(); |
| 2225 | bool IsCompatibleForLoad(PropertyAccessInfo* other); |
| 2226 | |
| 2227 | void GeneralizeRepresentation(Representation r) { |
| 2228 | access_ = access_.WithRepresentation( |
| 2229 | access_.representation().generalize(r)); |
| 2230 | } |
| 2231 | |
| 2232 | LookupResult lookup_; |
| 2233 | Handle<Map> map_; |
| 2234 | Handle<String> name_; |
| 2235 | Handle<JSObject> holder_; |
| 2236 | Handle<JSFunction> accessor_; |
| 2237 | Handle<Object> constant_; |
| 2238 | HObjectAccess access_; |
| 2239 | }; |
| 2240 | |
| 2241 | HInstruction* BuildLoadMonomorphic(PropertyAccessInfo* info, |
| 2242 | HValue* object, |
| 2243 | HInstruction* checked_object, |
| 2244 | BailoutId ast_id, |
| 2245 | BailoutId return_id, |
| 2246 | bool can_inline_accessor = true); |
| 2247 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 2248 | void HandlePolymorphicStoreNamedField(BailoutId assignment_id, |
danno@chromium.org | fe57867 | 2013-06-15 14:38:35 +0000 | [diff] [blame] | 2249 | HValue* object, |
dslomov@chromium.org | b752d40 | 2013-06-18 11:54:54 +0000 | [diff] [blame] | 2250 | HValue* value, |
danno@chromium.org | fe57867 | 2013-06-15 14:38:35 +0000 | [diff] [blame] | 2251 | SmallMapList* types, |
| 2252 | Handle<String> name); |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 2253 | bool TryStorePolymorphicAsMonomorphic(BailoutId assignment_id, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2254 | HValue* object, |
| 2255 | HValue* value, |
ricow@chromium.org | ddd545c | 2011-08-24 12:02:41 +0000 | [diff] [blame] | 2256 | SmallMapList* types, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2257 | Handle<String> name); |
| 2258 | void HandlePolymorphicCallNamed(Call* expr, |
| 2259 | HValue* receiver, |
ricow@chromium.org | ddd545c | 2011-08-24 12:02:41 +0000 | [diff] [blame] | 2260 | SmallMapList* types, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2261 | Handle<String> name); |
danno@chromium.org | bee5199 | 2013-07-10 14:57:15 +0000 | [diff] [blame] | 2262 | bool TryCallPolymorphicAsMonomorphic(Call* expr, |
| 2263 | HValue* receiver, |
| 2264 | SmallMapList* types, |
| 2265 | Handle<String> name); |
erik.corry@gmail.com | c3b670f | 2011-10-05 21:44:48 +0000 | [diff] [blame] | 2266 | void HandleLiteralCompareTypeof(CompareOperation* expr, |
jkummerow@chromium.org | 96a3c51 | 2013-07-18 17:02:47 +0000 | [diff] [blame] | 2267 | Expression* sub_expr, |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 2268 | Handle<String> check); |
erik.corry@gmail.com | c3b670f | 2011-10-05 21:44:48 +0000 | [diff] [blame] | 2269 | void HandleLiteralCompareNil(CompareOperation* expr, |
jkummerow@chromium.org | 96a3c51 | 2013-07-18 17:02:47 +0000 | [diff] [blame] | 2270 | Expression* sub_expr, |
erik.corry@gmail.com | c3b670f | 2011-10-05 21:44:48 +0000 | [diff] [blame] | 2271 | NilValue nil); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2272 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 2273 | HInstruction* BuildStringCharCodeAt(HValue* string, |
ulan@chromium.org | 2e04b58 | 2013-02-21 14:06:02 +0000 | [diff] [blame] | 2274 | HValue* index); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2275 | HInstruction* BuildBinaryOperation(BinaryOperation* expr, |
| 2276 | HValue* left, |
| 2277 | HValue* right); |
kmillikin@chromium.org | c53e10d | 2011-05-18 09:12:58 +0000 | [diff] [blame] | 2278 | HInstruction* BuildIncrement(bool returns_original_input, |
sgjesse@chromium.org | 8e8294a | 2011-05-02 14:30:53 +0000 | [diff] [blame] | 2279 | CountOperation* expr); |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 2280 | HInstruction* BuildLoadKeyedGeneric(HValue* object, |
| 2281 | HValue* key); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2282 | |
mstarzinger@chromium.org | c6d9cee | 2012-07-03 10:03:19 +0000 | [diff] [blame] | 2283 | HInstruction* TryBuildConsolidatedElementLoad(HValue* object, |
| 2284 | HValue* key, |
| 2285 | HValue* val, |
| 2286 | SmallMapList* maps); |
| 2287 | |
jkummerow@chromium.org | 1e8da74 | 2013-08-26 17:13:35 +0000 | [diff] [blame] | 2288 | LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map); |
| 2289 | |
whesse@chromium.org | 7b26015 | 2011-06-20 15:33:18 +0000 | [diff] [blame] | 2290 | HInstruction* BuildMonomorphicElementAccess(HValue* object, |
| 2291 | HValue* key, |
| 2292 | HValue* val, |
svenpanne@chromium.org | 830d30c | 2012-05-29 13:20:14 +0000 | [diff] [blame] | 2293 | HValue* dependency, |
erik.corry@gmail.com | 394dbcf | 2011-10-27 07:38:48 +0000 | [diff] [blame] | 2294 | Handle<Map> map, |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 2295 | bool is_store, |
| 2296 | KeyedAccessStoreMode store_mode); |
mstarzinger@chromium.org | c6d9cee | 2012-07-03 10:03:19 +0000 | [diff] [blame] | 2297 | |
whesse@chromium.org | 7b26015 | 2011-06-20 15:33:18 +0000 | [diff] [blame] | 2298 | HValue* HandlePolymorphicElementAccess(HValue* object, |
| 2299 | HValue* key, |
| 2300 | HValue* val, |
dslomov@chromium.org | 4a35c5a | 2013-09-13 07:28:52 +0000 | [diff] [blame] | 2301 | SmallMapList* maps, |
whesse@chromium.org | 7b26015 | 2011-06-20 15:33:18 +0000 | [diff] [blame] | 2302 | bool is_store, |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 2303 | KeyedAccessStoreMode store_mode, |
whesse@chromium.org | 7b26015 | 2011-06-20 15:33:18 +0000 | [diff] [blame] | 2304 | bool* has_side_effects); |
| 2305 | |
| 2306 | HValue* HandleKeyedElementAccess(HValue* obj, |
| 2307 | HValue* key, |
| 2308 | HValue* val, |
| 2309 | Expression* expr, |
whesse@chromium.org | 7b26015 | 2011-06-20 15:33:18 +0000 | [diff] [blame] | 2310 | bool is_store, |
| 2311 | bool* has_side_effects); |
karlklose@chromium.org | 44bc708 | 2011-04-11 12:33:05 +0000 | [diff] [blame] | 2312 | |
ulan@chromium.org | ea52b5f | 2012-07-30 13:05:33 +0000 | [diff] [blame] | 2313 | HInstruction* BuildLoadNamedGeneric(HValue* object, |
| 2314 | Handle<String> name, |
| 2315 | Property* expr); |
ulan@chromium.org | ea52b5f | 2012-07-30 13:05:33 +0000 | [diff] [blame] | 2316 | |
verwaest@chromium.org | 003a925 | 2013-08-12 17:15:20 +0000 | [diff] [blame] | 2317 | HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 2318 | |
jkummerow@chromium.org | 3d00d0a | 2013-09-04 13:57:32 +0000 | [diff] [blame] | 2319 | void BuildLoad(Property* property, |
jkummerow@chromium.org | 3d00d0a | 2013-09-04 13:57:32 +0000 | [diff] [blame] | 2320 | BailoutId ast_id); |
| 2321 | void PushLoad(Property* property, |
| 2322 | HValue* object, |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 2323 | HValue* key); |
jkummerow@chromium.org | 3d00d0a | 2013-09-04 13:57:32 +0000 | [diff] [blame] | 2324 | |
dslomov@chromium.org | 639bac0 | 2013-09-09 11:58:54 +0000 | [diff] [blame] | 2325 | void BuildStoreForEffect(Expression* expression, |
| 2326 | Property* prop, |
| 2327 | BailoutId ast_id, |
| 2328 | BailoutId return_id, |
| 2329 | HValue* object, |
| 2330 | HValue* key, |
| 2331 | HValue* value); |
jkummerow@chromium.org | 2c9426b | 2013-09-05 16:31:13 +0000 | [diff] [blame] | 2332 | |
dslomov@chromium.org | 639bac0 | 2013-09-09 11:58:54 +0000 | [diff] [blame] | 2333 | void BuildStore(Expression* expression, |
| 2334 | Property* prop, |
| 2335 | BailoutId ast_id, |
| 2336 | BailoutId return_id, |
| 2337 | bool is_uninitialized = false); |
danno@chromium.org | b0deb65 | 2013-06-20 16:20:19 +0000 | [diff] [blame] | 2338 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2339 | HInstruction* BuildStoreNamedField(HValue* object, |
| 2340 | Handle<String> name, |
| 2341 | HValue* value, |
verwaest@chromium.org | b6d052d | 2012-07-27 08:03:27 +0000 | [diff] [blame] | 2342 | Handle<Map> map, |
verwaest@chromium.org | e4ee6de | 2012-11-06 12:13:00 +0000 | [diff] [blame] | 2343 | LookupResult* lookup); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2344 | HInstruction* BuildStoreNamedGeneric(HValue* object, |
| 2345 | Handle<String> name, |
| 2346 | HValue* value); |
ulan@chromium.org | ea52b5f | 2012-07-30 13:05:33 +0000 | [diff] [blame] | 2347 | HInstruction* BuildStoreNamedMonomorphic(HValue* object, |
| 2348 | Handle<String> name, |
| 2349 | HValue* value, |
| 2350 | Handle<Map> map); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2351 | HInstruction* BuildStoreKeyedGeneric(HValue* object, |
| 2352 | HValue* key, |
| 2353 | HValue* value); |
| 2354 | |
ricow@chromium.org | 83aa549 | 2011-02-07 12:42:56 +0000 | [diff] [blame] | 2355 | HValue* BuildContextChainWalk(Variable* var); |
| 2356 | |
yangguo@chromium.org | 5a11aaf | 2012-06-20 11:29:00 +0000 | [diff] [blame] | 2357 | HInstruction* BuildThisFunction(); |
| 2358 | |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 2359 | HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object, |
| 2360 | AllocationSiteContext* site_context); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 2361 | |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2362 | void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object, |
| 2363 | HInstruction* object); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 2364 | |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2365 | void BuildInitElementsInObjectHeader(Handle<JSObject> boilerplate_object, |
| 2366 | HInstruction* object, |
| 2367 | HInstruction* object_elements); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 2368 | |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 2369 | void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object, |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 2370 | HInstruction* object, |
| 2371 | AllocationSiteContext* site_context); |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 2372 | |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2373 | void BuildEmitElements(Handle<JSObject> boilerplate_object, |
| 2374 | Handle<FixedArrayBase> elements, |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 2375 | HValue* object_elements, |
| 2376 | AllocationSiteContext* site_context); |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 2377 | |
| 2378 | void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements, |
| 2379 | ElementsKind kind, |
| 2380 | HValue* object_elements); |
| 2381 | |
| 2382 | void BuildEmitFixedArray(Handle<FixedArrayBase> elements, |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 2383 | ElementsKind kind, |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 2384 | HValue* object_elements, |
| 2385 | AllocationSiteContext* site_context); |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 2386 | |
verwaest@chromium.org | e4ee6de | 2012-11-06 12:13:00 +0000 | [diff] [blame] | 2387 | void AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 2388 | Handle<Map> receiver_map); |
| 2389 | |
yangguo@chromium.org | 99aa490 | 2012-07-06 16:21:55 +0000 | [diff] [blame] | 2390 | void AddCheckConstantFunction(Handle<JSObject> holder, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2391 | HValue* receiver, |
verwaest@chromium.org | e4ee6de | 2012-11-06 12:13:00 +0000 | [diff] [blame] | 2392 | Handle<Map> receiver_map); |
| 2393 | |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2394 | // The translation state of the currently-being-translated function. |
| 2395 | FunctionState* function_state_; |
| 2396 | |
| 2397 | // The base of the function state stack. |
| 2398 | FunctionState initial_function_state_; |
| 2399 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2400 | // Expression context of the currently visited subexpression. NULL when |
| 2401 | // visiting statements. |
| 2402 | AstContext* ast_context_; |
| 2403 | |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2404 | // A stack of breakable statements entered. |
| 2405 | BreakAndContinueScope* break_scope_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2406 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2407 | int inlined_count_; |
erik.corry@gmail.com | ed49e96 | 2012-04-17 11:57:53 +0000 | [diff] [blame] | 2408 | ZoneList<Handle<Object> > globals_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2409 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 2410 | bool inline_bailout_; |
| 2411 | |
machenbach@chromium.org | c1789ee | 2013-07-05 07:09:57 +0000 | [diff] [blame] | 2412 | HOsrBuilder* osr_; |
| 2413 | |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2414 | friend class FunctionState; // Pushes and pops the state stack. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2415 | friend class AstContext; // Pushes and pops the AST context stack. |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 2416 | friend class KeyedLoadFastElementStub; |
machenbach@chromium.org | c1789ee | 2013-07-05 07:09:57 +0000 | [diff] [blame] | 2417 | friend class HOsrBuilder; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2418 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 2419 | DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2420 | }; |
| 2421 | |
| 2422 | |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 2423 | Zone* AstContext::zone() const { return owner_->zone(); } |
vegorov@chromium.org | 74f333b | 2011-04-06 11:17:46 +0000 | [diff] [blame] | 2424 | |
| 2425 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2426 | class HStatistics V8_FINAL: public Malloced { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2427 | public: |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 2428 | HStatistics() |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2429 | : times_(5), |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 2430 | names_(5), |
| 2431 | sizes_(5), |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 2432 | total_size_(0), |
whesse@chromium.org | b08986c | 2011-03-14 16:13:42 +0000 | [diff] [blame] | 2433 | source_size_(0) { } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2434 | |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2435 | void Initialize(CompilationInfo* info); |
| 2436 | void Print(); |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2437 | void SaveTiming(const char* name, TimeDelta time, unsigned size); |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2438 | |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2439 | void IncrementFullCodeGen(TimeDelta full_code_gen) { |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2440 | full_code_gen_ += full_code_gen; |
| 2441 | } |
| 2442 | |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2443 | void IncrementSubtotals(TimeDelta create_graph, |
| 2444 | TimeDelta optimize_graph, |
| 2445 | TimeDelta generate_code) { |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2446 | create_graph_ += create_graph; |
| 2447 | optimize_graph_ += optimize_graph; |
| 2448 | generate_code_ += generate_code; |
| 2449 | } |
| 2450 | |
| 2451 | private: |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2452 | List<TimeDelta> times_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2453 | List<const char*> names_; |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 2454 | List<unsigned> sizes_; |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2455 | TimeDelta create_graph_; |
| 2456 | TimeDelta optimize_graph_; |
| 2457 | TimeDelta generate_code_; |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 2458 | unsigned total_size_; |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2459 | TimeDelta full_code_gen_; |
whesse@chromium.org | b08986c | 2011-03-14 16:13:42 +0000 | [diff] [blame] | 2460 | double source_size_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2461 | }; |
| 2462 | |
| 2463 | |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2464 | class HPhase : public CompilationPhase { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2465 | public: |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2466 | HPhase(const char* name, HGraph* graph) |
| 2467 | : CompilationPhase(name, graph->info()), |
| 2468 | graph_(graph) { } |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2469 | ~HPhase(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2470 | |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2471 | protected: |
| 2472 | HGraph* graph() const { return graph_; } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2473 | |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2474 | private: |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2475 | HGraph* graph_; |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2476 | |
| 2477 | DISALLOW_COPY_AND_ASSIGN(HPhase); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2478 | }; |
| 2479 | |
| 2480 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2481 | class HTracer V8_FINAL : public Malloced { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2482 | public: |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2483 | explicit HTracer(int isolate_id) |
| 2484 | : trace_(&string_allocator_), indent_(0) { |
jkummerow@chromium.org | fb732b1 | 2013-07-26 10:27:09 +0000 | [diff] [blame] | 2485 | if (FLAG_trace_hydrogen_file == NULL) { |
| 2486 | OS::SNPrintF(filename_, |
| 2487 | "hydrogen-%d-%d.cfg", |
| 2488 | OS::GetCurrentProcessId(), |
| 2489 | isolate_id); |
| 2490 | } else { |
| 2491 | OS::StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length()); |
| 2492 | } |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2493 | WriteChars(filename_.start(), "", 0, false); |
| 2494 | } |
| 2495 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 2496 | void TraceCompilation(CompilationInfo* info); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2497 | void TraceHydrogen(const char* name, HGraph* graph); |
jkummerow@chromium.org | 28583c9 | 2012-07-16 11:31:55 +0000 | [diff] [blame] | 2498 | void TraceLithium(const char* name, LChunk* chunk); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2499 | void TraceLiveRanges(const char* name, LAllocator* allocator); |
| 2500 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2501 | private: |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2502 | class Tag V8_FINAL BASE_EMBEDDED { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2503 | public: |
| 2504 | Tag(HTracer* tracer, const char* name) { |
| 2505 | name_ = name; |
| 2506 | tracer_ = tracer; |
| 2507 | tracer->PrintIndent(); |
| 2508 | tracer->trace_.Add("begin_%s\n", name); |
| 2509 | tracer->indent_++; |
| 2510 | } |
| 2511 | |
| 2512 | ~Tag() { |
| 2513 | tracer_->indent_--; |
| 2514 | tracer_->PrintIndent(); |
| 2515 | tracer_->trace_.Add("end_%s\n", name_); |
| 2516 | ASSERT(tracer_->indent_ >= 0); |
| 2517 | tracer_->FlushToFile(); |
| 2518 | } |
| 2519 | |
| 2520 | private: |
| 2521 | HTracer* tracer_; |
| 2522 | const char* name_; |
| 2523 | }; |
| 2524 | |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 2525 | void TraceLiveRange(LiveRange* range, const char* type, Zone* zone); |
jkummerow@chromium.org | 28583c9 | 2012-07-16 11:31:55 +0000 | [diff] [blame] | 2526 | void Trace(const char* name, HGraph* graph, LChunk* chunk); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2527 | void FlushToFile(); |
| 2528 | |
| 2529 | void PrintEmptyProperty(const char* name) { |
| 2530 | PrintIndent(); |
| 2531 | trace_.Add("%s\n", name); |
| 2532 | } |
| 2533 | |
| 2534 | void PrintStringProperty(const char* name, const char* value) { |
| 2535 | PrintIndent(); |
| 2536 | trace_.Add("%s \"%s\"\n", name, value); |
| 2537 | } |
| 2538 | |
| 2539 | void PrintLongProperty(const char* name, int64_t value) { |
| 2540 | PrintIndent(); |
| 2541 | trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000)); |
| 2542 | } |
| 2543 | |
| 2544 | void PrintBlockProperty(const char* name, int block_id) { |
| 2545 | PrintIndent(); |
| 2546 | trace_.Add("%s \"B%d\"\n", name, block_id); |
| 2547 | } |
| 2548 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2549 | void PrintIntProperty(const char* name, int value) { |
| 2550 | PrintIndent(); |
| 2551 | trace_.Add("%s %d\n", name, value); |
| 2552 | } |
| 2553 | |
| 2554 | void PrintIndent() { |
| 2555 | for (int i = 0; i < indent_; i++) { |
| 2556 | trace_.Add(" "); |
| 2557 | } |
| 2558 | } |
| 2559 | |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2560 | EmbeddedVector<char, 64> filename_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2561 | HeapStringAllocator string_allocator_; |
| 2562 | StringStream trace_; |
| 2563 | int indent_; |
| 2564 | }; |
| 2565 | |
| 2566 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2567 | class NoObservableSideEffectsScope V8_FINAL { |
danno@chromium.org | ad75d6f | 2013-08-12 16:57:59 +0000 | [diff] [blame] | 2568 | public: |
| 2569 | explicit NoObservableSideEffectsScope(HGraphBuilder* builder) : |
| 2570 | builder_(builder) { |
| 2571 | builder_->graph()->IncrementInNoSideEffectsScope(); |
| 2572 | } |
| 2573 | ~NoObservableSideEffectsScope() { |
| 2574 | builder_->graph()->DecrementInNoSideEffectsScope(); |
| 2575 | } |
| 2576 | |
| 2577 | private: |
| 2578 | HGraphBuilder* builder_; |
| 2579 | }; |
| 2580 | |
| 2581 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2582 | } } // namespace v8::internal |
| 2583 | |
| 2584 | #endif // V8_HYDROGEN_H_ |