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 | |
ulan@chromium.org | 0f13e74 | 2014-01-03 15:51:11 +0000 | [diff] [blame^] | 998 | class HAllocationMode V8_FINAL BASE_EMBEDDED { |
| 999 | public: |
| 1000 | explicit HAllocationMode(Handle<AllocationSite> feedback_site) |
| 1001 | : current_site_(NULL), feedback_site_(feedback_site), |
| 1002 | pretenure_flag_(NOT_TENURED) {} |
| 1003 | explicit HAllocationMode(HValue* current_site) |
| 1004 | : current_site_(current_site), pretenure_flag_(NOT_TENURED) {} |
| 1005 | explicit HAllocationMode(PretenureFlag pretenure_flag) |
| 1006 | : current_site_(NULL), pretenure_flag_(pretenure_flag) {} |
| 1007 | |
| 1008 | HValue* current_site() const { return current_site_; } |
| 1009 | Handle<AllocationSite> feedback_site() const { return feedback_site_; } |
| 1010 | |
| 1011 | bool CreateAllocationMementos() const V8_WARN_UNUSED_RESULT { |
| 1012 | return current_site() != NULL; |
| 1013 | } |
| 1014 | |
| 1015 | PretenureFlag GetPretenureMode() const V8_WARN_UNUSED_RESULT { |
| 1016 | if (!feedback_site().is_null()) return feedback_site()->GetPretenureMode(); |
| 1017 | return pretenure_flag_; |
| 1018 | } |
| 1019 | |
| 1020 | private: |
| 1021 | HValue* current_site_; |
| 1022 | Handle<AllocationSite> feedback_site_; |
| 1023 | PretenureFlag pretenure_flag_; |
| 1024 | }; |
| 1025 | |
| 1026 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1027 | class HGraphBuilder { |
| 1028 | public: |
| 1029 | explicit HGraphBuilder(CompilationInfo* info) |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 1030 | : info_(info), |
| 1031 | graph_(NULL), |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1032 | current_block_(NULL), |
| 1033 | position_(RelocInfo::kNoPosition) {} |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1034 | virtual ~HGraphBuilder() {} |
| 1035 | |
| 1036 | HBasicBlock* current_block() const { return current_block_; } |
| 1037 | void set_current_block(HBasicBlock* block) { current_block_ = block; } |
| 1038 | HEnvironment* environment() const { |
| 1039 | return current_block()->last_environment(); |
| 1040 | } |
| 1041 | Zone* zone() const { return info_->zone(); } |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 1042 | HGraph* graph() const { return graph_; } |
| 1043 | Isolate* isolate() const { return graph_->isolate(); } |
danno@chromium.org | 4172848 | 2013-06-12 22:31:22 +0000 | [diff] [blame] | 1044 | CompilationInfo* top_info() { return info_; } |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1045 | |
| 1046 | HGraph* CreateGraph(); |
| 1047 | |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1048 | // Bailout environment manipulation. |
| 1049 | void Push(HValue* value) { environment()->Push(value); } |
| 1050 | HValue* Pop() { return environment()->Pop(); } |
| 1051 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1052 | virtual HValue* context() = 0; |
| 1053 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1054 | // Adding instructions. |
| 1055 | HInstruction* AddInstruction(HInstruction* instr); |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1056 | void FinishCurrentBlock(HControlInstruction* last); |
| 1057 | void FinishExitCurrentBlock(HControlInstruction* instruction); |
| 1058 | |
| 1059 | void Goto(HBasicBlock* from, |
| 1060 | HBasicBlock* target, |
| 1061 | FunctionState* state = NULL, |
| 1062 | bool add_simulate = true) { |
| 1063 | from->Goto(target, position_, state, add_simulate); |
| 1064 | } |
| 1065 | void Goto(HBasicBlock* target, |
| 1066 | FunctionState* state = NULL, |
| 1067 | bool add_simulate = true) { |
| 1068 | Goto(current_block(), target, state, add_simulate); |
| 1069 | } |
| 1070 | void GotoNoSimulate(HBasicBlock* from, HBasicBlock* target) { |
| 1071 | Goto(from, target, NULL, false); |
| 1072 | } |
| 1073 | void GotoNoSimulate(HBasicBlock* target) { |
| 1074 | Goto(target, NULL, false); |
| 1075 | } |
| 1076 | void AddLeaveInlined(HBasicBlock* block, |
| 1077 | HValue* return_value, |
| 1078 | FunctionState* state) { |
| 1079 | block->AddLeaveInlined(return_value, state, position_); |
| 1080 | } |
| 1081 | void AddLeaveInlined(HValue* return_value, FunctionState* state) { |
| 1082 | return AddLeaveInlined(current_block(), return_value, state); |
| 1083 | } |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1084 | |
| 1085 | template<class I> |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1086 | HInstruction* NewUncasted() { return I::New(zone(), context()); } |
| 1087 | |
| 1088 | template<class I> |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1089 | I* New() { return I::New(zone(), context()); } |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1090 | |
| 1091 | template<class I> |
| 1092 | HInstruction* AddUncasted() { return AddInstruction(NewUncasted<I>());} |
| 1093 | |
| 1094 | template<class I> |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1095 | I* Add() { return AddInstructionTyped(New<I>());} |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1096 | |
| 1097 | template<class I, class P1> |
| 1098 | HInstruction* NewUncasted(P1 p1) { |
| 1099 | return I::New(zone(), context(), p1); |
| 1100 | } |
| 1101 | |
| 1102 | template<class I, class P1> |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1103 | I* New(P1 p1) { return I::New(zone(), context(), p1); } |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1104 | |
| 1105 | template<class I, class P1> |
| 1106 | HInstruction* AddUncasted(P1 p1) { |
| 1107 | HInstruction* result = AddInstruction(NewUncasted<I>(p1)); |
| 1108 | // Specializations must have their parameters properly casted |
| 1109 | // to avoid landing here. |
| 1110 | ASSERT(!result->IsReturn() && !result->IsSimulate() && |
| 1111 | !result->IsDeoptimize()); |
| 1112 | return result; |
| 1113 | } |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1114 | |
| 1115 | template<class I, class P1> |
| 1116 | I* Add(P1 p1) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1117 | I* result = AddInstructionTyped(New<I>(p1)); |
| 1118 | // Specializations must have their parameters properly casted |
| 1119 | // to avoid landing here. |
| 1120 | ASSERT(!result->IsReturn() && !result->IsSimulate() && |
| 1121 | !result->IsDeoptimize()); |
| 1122 | return result; |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1123 | } |
| 1124 | |
| 1125 | template<class I, class P1, class P2> |
| 1126 | HInstruction* NewUncasted(P1 p1, P2 p2) { |
| 1127 | return I::New(zone(), context(), p1, p2); |
| 1128 | } |
| 1129 | |
| 1130 | template<class I, class P1, class P2> |
| 1131 | I* New(P1 p1, P2 p2) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1132 | return I::New(zone(), context(), p1, p2); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1133 | } |
| 1134 | |
| 1135 | template<class I, class P1, class P2> |
| 1136 | HInstruction* AddUncasted(P1 p1, P2 p2) { |
| 1137 | HInstruction* result = AddInstruction(NewUncasted<I>(p1, p2)); |
| 1138 | // Specializations must have their parameters properly casted |
| 1139 | // to avoid landing here. |
| 1140 | ASSERT(!result->IsSimulate()); |
| 1141 | return result; |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1142 | } |
| 1143 | |
| 1144 | template<class I, class P1, class P2> |
| 1145 | I* Add(P1 p1, P2 p2) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1146 | I* result = AddInstructionTyped(New<I>(p1, p2)); |
| 1147 | // Specializations must have their parameters properly casted |
| 1148 | // to avoid landing here. |
| 1149 | ASSERT(!result->IsSimulate()); |
| 1150 | return result; |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1151 | } |
| 1152 | |
| 1153 | template<class I, class P1, class P2, class P3> |
| 1154 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3) { |
| 1155 | return I::New(zone(), context(), p1, p2, p3); |
| 1156 | } |
| 1157 | |
| 1158 | template<class I, class P1, class P2, class P3> |
| 1159 | I* New(P1 p1, P2 p2, P3 p3) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1160 | return I::New(zone(), context(), p1, p2, p3); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1161 | } |
| 1162 | |
| 1163 | template<class I, class P1, class P2, class P3> |
| 1164 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3) { |
| 1165 | return AddInstruction(NewUncasted<I>(p1, p2, p3)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1166 | } |
| 1167 | |
| 1168 | template<class I, class P1, class P2, class P3> |
| 1169 | I* Add(P1 p1, P2 p2, P3 p3) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1170 | return AddInstructionTyped(New<I>(p1, p2, p3)); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1171 | } |
| 1172 | |
| 1173 | template<class I, class P1, class P2, class P3, class P4> |
| 1174 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4) { |
| 1175 | return I::New(zone(), context(), p1, p2, p3, p4); |
| 1176 | } |
| 1177 | |
| 1178 | template<class I, class P1, class P2, class P3, class P4> |
| 1179 | I* New(P1 p1, P2 p2, P3 p3, P4 p4) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1180 | return I::New(zone(), context(), p1, p2, p3, p4); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1181 | } |
| 1182 | |
| 1183 | template<class I, class P1, class P2, class P3, class P4> |
| 1184 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4) { |
| 1185 | return AddInstruction(NewUncasted<I>(p1, p2, p3, p4)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1186 | } |
| 1187 | |
| 1188 | template<class I, class P1, class P2, class P3, class P4> |
| 1189 | I* Add(P1 p1, P2 p2, P3 p3, P4 p4) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1190 | return AddInstructionTyped(New<I>(p1, p2, p3, p4)); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1191 | } |
| 1192 | |
| 1193 | template<class I, class P1, class P2, class P3, class P4, class P5> |
| 1194 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { |
| 1195 | return I::New(zone(), context(), p1, p2, p3, p4, p5); |
| 1196 | } |
| 1197 | |
| 1198 | template<class I, class P1, class P2, class P3, class P4, class P5> |
| 1199 | I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1200 | return I::New(zone(), context(), p1, p2, p3, p4, p5); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1201 | } |
| 1202 | |
| 1203 | template<class I, class P1, class P2, class P3, class P4, class P5> |
| 1204 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { |
| 1205 | return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1206 | } |
| 1207 | |
| 1208 | template<class I, class P1, class P2, class P3, class P4, class P5> |
| 1209 | I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1210 | return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5)); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1211 | } |
| 1212 | |
| 1213 | template<class I, class P1, class P2, class P3, class P4, class P5, class P6> |
| 1214 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { |
| 1215 | return I::New(zone(), context(), p1, p2, p3, p4, p5, p6); |
| 1216 | } |
| 1217 | |
| 1218 | template<class I, class P1, class P2, class P3, class P4, class P5, class P6> |
| 1219 | I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1220 | return I::New(zone(), context(), p1, p2, p3, p4, p5, p6); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1221 | } |
| 1222 | |
| 1223 | template<class I, class P1, class P2, class P3, class P4, class P5, class P6> |
| 1224 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { |
| 1225 | return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1226 | } |
| 1227 | |
| 1228 | template<class I, class P1, class P2, class P3, class P4, class P5, class P6> |
| 1229 | I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1230 | return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6)); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1231 | } |
| 1232 | |
| 1233 | template<class I, class P1, class P2, class P3, class P4, |
| 1234 | class P5, class P6, class P7> |
| 1235 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { |
| 1236 | return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7); |
| 1237 | } |
| 1238 | |
| 1239 | template<class I, class P1, class P2, class P3, class P4, |
| 1240 | class P5, class P6, class P7> |
| 1241 | I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1242 | return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1243 | } |
| 1244 | |
| 1245 | template<class I, class P1, class P2, class P3, |
| 1246 | class P4, class P5, class P6, class P7> |
| 1247 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { |
| 1248 | return AddInstruction(NewUncasted<I>(p1, p2, p3, p4, p5, p6, p7)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1249 | } |
| 1250 | |
| 1251 | template<class I, class P1, class P2, class P3, |
| 1252 | class P4, class P5, class P6, class P7> |
| 1253 | I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1254 | return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7)); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1255 | } |
| 1256 | |
| 1257 | template<class I, class P1, class P2, class P3, class P4, |
| 1258 | class P5, class P6, class P7, class P8> |
| 1259 | HInstruction* NewUncasted(P1 p1, P2 p2, P3 p3, P4 p4, |
| 1260 | P5 p5, P6 p6, P7 p7, P8 p8) { |
| 1261 | return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8); |
| 1262 | } |
| 1263 | |
| 1264 | template<class I, class P1, class P2, class P3, class P4, |
| 1265 | class P5, class P6, class P7, class P8> |
| 1266 | I* New(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1267 | return I::New(zone(), context(), p1, p2, p3, p4, p5, p6, p7, p8); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1268 | } |
| 1269 | |
| 1270 | template<class I, class P1, class P2, class P3, class P4, |
| 1271 | class P5, class P6, class P7, class P8> |
| 1272 | HInstruction* AddUncasted(P1 p1, P2 p2, P3 p3, P4 p4, |
| 1273 | P5 p5, P6 p6, P7 p7, P8 p8) { |
| 1274 | 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] | 1275 | } |
| 1276 | |
| 1277 | template<class I, class P1, class P2, class P3, class P4, |
| 1278 | class P5, class P6, class P7, class P8> |
| 1279 | I* Add(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1280 | return AddInstructionTyped(New<I>(p1, p2, p3, p4, p5, p6, p7, p8)); |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1281 | } |
| 1282 | |
danno@chromium.org | ad75d6f | 2013-08-12 16:57:59 +0000 | [diff] [blame] | 1283 | void AddSimulate(BailoutId id, RemovableSimulate removable = FIXED_SIMULATE); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 1284 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1285 | int position() const { return position_; } |
| 1286 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1287 | protected: |
| 1288 | virtual bool BuildGraph() = 0; |
| 1289 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1290 | HBasicBlock* CreateBasicBlock(HEnvironment* env); |
| 1291 | HBasicBlock* CreateLoopHeaderBlock(); |
| 1292 | |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1293 | HValue* BuildCheckHeapObject(HValue* object); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1294 | HValue* BuildCheckMap(HValue* obj, Handle<Map> map); |
machenbach@chromium.org | 90dca01 | 2013-11-22 10:04:21 +0000 | [diff] [blame] | 1295 | HValue* BuildCheckString(HValue* string); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1296 | HValue* BuildWrapReceiver(HValue* object, HValue* function); |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1297 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1298 | // Building common constructs |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1299 | HValue* BuildCheckForCapacityGrow(HValue* object, |
| 1300 | HValue* elements, |
| 1301 | ElementsKind kind, |
| 1302 | HValue* length, |
| 1303 | HValue* key, |
hpayer@chromium.org | 71ea97f | 2013-12-19 16:03:26 +0000 | [diff] [blame] | 1304 | bool is_js_array, |
| 1305 | bool is_store); |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1306 | |
| 1307 | HValue* BuildCopyElementsOnWrite(HValue* object, |
| 1308 | HValue* elements, |
| 1309 | ElementsKind kind, |
| 1310 | HValue* length); |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1311 | |
jkummerow@chromium.org | ba72ec8 | 2013-07-22 09:21:20 +0000 | [diff] [blame] | 1312 | void BuildTransitionElementsKind(HValue* object, |
| 1313 | HValue* map, |
| 1314 | ElementsKind from_kind, |
| 1315 | ElementsKind to_kind, |
| 1316 | bool is_jsarray); |
| 1317 | |
bmeurer@chromium.org | e7a0745 | 2013-10-21 13:27:29 +0000 | [diff] [blame] | 1318 | HValue* BuildNumberToString(HValue* object, Handle<Type> type); |
machenbach@chromium.org | 3d079fe | 2013-09-25 08:19:55 +0000 | [diff] [blame] | 1319 | |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame] | 1320 | HValue* BuildUncheckedDictionaryElementLoad(HValue* receiver, |
| 1321 | HValue* key); |
| 1322 | |
ulan@chromium.org | 0f13e74 | 2014-01-03 15:51:11 +0000 | [diff] [blame^] | 1323 | // Allocates a new object according with the given allocation properties. |
| 1324 | HAllocate* BuildAllocate(HValue* object_size, |
| 1325 | HType type, |
| 1326 | InstanceType instance_type, |
| 1327 | HAllocationMode allocation_mode); |
| 1328 | // Computes the sum of two string lengths, taking care of overflow handling. |
| 1329 | HValue* BuildAddStringLengths(HValue* left_length, HValue* right_length); |
| 1330 | // Creates a cons string using the two input strings. |
| 1331 | HValue* BuildCreateConsString(HValue* length, |
| 1332 | HValue* left, |
| 1333 | HValue* right, |
| 1334 | HAllocationMode allocation_mode); |
machenbach@chromium.org | 0cc0950 | 2013-11-13 12:20:55 +0000 | [diff] [blame] | 1335 | // Copies characters from one sequential string to another. |
| 1336 | void BuildCopySeqStringChars(HValue* src, |
| 1337 | HValue* src_offset, |
| 1338 | String::Encoding src_encoding, |
| 1339 | HValue* dst, |
| 1340 | HValue* dst_offset, |
| 1341 | String::Encoding dst_encoding, |
| 1342 | HValue* length); |
| 1343 | // Both operands are non-empty strings. |
| 1344 | HValue* BuildUncheckedStringAdd(HValue* left, |
| 1345 | HValue* right, |
ulan@chromium.org | 0f13e74 | 2014-01-03 15:51:11 +0000 | [diff] [blame^] | 1346 | HAllocationMode allocation_mode); |
| 1347 | // Add two strings using allocation mode, validating type feedback. |
machenbach@chromium.org | 0cc0950 | 2013-11-13 12:20:55 +0000 | [diff] [blame] | 1348 | HValue* BuildStringAdd(HValue* left, |
| 1349 | HValue* right, |
ulan@chromium.org | 0f13e74 | 2014-01-03 15:51:11 +0000 | [diff] [blame^] | 1350 | HAllocationMode allocation_mode); |
machenbach@chromium.org | 0cc0950 | 2013-11-13 12:20:55 +0000 | [diff] [blame] | 1351 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1352 | HInstruction* BuildUncheckedMonomorphicElementAccess( |
jkummerow@chromium.org | 1e8da74 | 2013-08-26 17:13:35 +0000 | [diff] [blame] | 1353 | HValue* checked_object, |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1354 | HValue* key, |
| 1355 | HValue* val, |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1356 | bool is_js_array, |
| 1357 | ElementsKind elements_kind, |
mstarzinger@chromium.org | 068ea0a | 2013-01-30 09:39:44 +0000 | [diff] [blame] | 1358 | bool is_store, |
ulan@chromium.org | 906e2fb | 2013-05-14 08:14:38 +0000 | [diff] [blame] | 1359 | LoadKeyedHoleMode load_mode, |
svenpanne@chromium.org | 53ad175 | 2013-05-27 12:20:38 +0000 | [diff] [blame] | 1360 | KeyedAccessStoreMode store_mode); |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1361 | |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 1362 | HInstruction* AddElementAccess( |
jkummerow@chromium.org | ba72ec8 | 2013-07-22 09:21:20 +0000 | [diff] [blame] | 1363 | HValue* elements, |
| 1364 | HValue* checked_key, |
| 1365 | HValue* val, |
| 1366 | HValue* dependency, |
| 1367 | ElementsKind elements_kind, |
| 1368 | bool is_store, |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 1369 | LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE); |
jkummerow@chromium.org | ba72ec8 | 2013-07-22 09:21:20 +0000 | [diff] [blame] | 1370 | |
verwaest@chromium.org | ec6855e | 2013-08-22 12:26:58 +0000 | [diff] [blame] | 1371 | HLoadNamedField* BuildLoadNamedField(HValue* object, HObjectAccess access); |
bmeurer@chromium.org | db78329 | 2013-10-23 06:51:00 +0000 | [diff] [blame] | 1372 | HInstruction* AddLoadNamedField(HValue* object, HObjectAccess access); |
ulan@chromium.org | 0f13e74 | 2014-01-03 15:51:11 +0000 | [diff] [blame^] | 1373 | HInstruction* AddLoadStringInstanceType(HValue* string); |
| 1374 | HInstruction* AddLoadStringLength(HValue* string); |
| 1375 | HStoreNamedField* AddStoreMapNoWriteBarrier(HValue* object, HValue* map) { |
| 1376 | HStoreNamedField* store_map = Add<HStoreNamedField>( |
| 1377 | object, HObjectAccess::ForMap(), map); |
| 1378 | store_map->SkipWriteBarrier(); |
| 1379 | return store_map; |
| 1380 | } |
machenbach@chromium.org | 0cc0950 | 2013-11-13 12:20:55 +0000 | [diff] [blame] | 1381 | HStoreNamedField* AddStoreMapConstant(HValue* object, Handle<Map> map); |
| 1382 | HStoreNamedField* AddStoreMapConstantNoWriteBarrier(HValue* object, |
| 1383 | Handle<Map> map) { |
| 1384 | HStoreNamedField* store_map = AddStoreMapConstant(object, map); |
| 1385 | store_map->SkipWriteBarrier(); |
| 1386 | return store_map; |
| 1387 | } |
verwaest@chromium.org | ec6855e | 2013-08-22 12:26:58 +0000 | [diff] [blame] | 1388 | HLoadNamedField* AddLoadElements(HValue* object); |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1389 | |
| 1390 | bool MatchRotateRight(HValue* left, |
| 1391 | HValue* right, |
| 1392 | HValue** operand, |
| 1393 | HValue** shift_amount); |
| 1394 | |
machenbach@chromium.org | 7ff7607 | 2013-11-21 09:47:43 +0000 | [diff] [blame] | 1395 | HValue* BuildBinaryOperation(Token::Value op, |
| 1396 | HValue* left, |
| 1397 | HValue* right, |
| 1398 | Handle<Type> left_type, |
| 1399 | Handle<Type> right_type, |
| 1400 | Handle<Type> result_type, |
ulan@chromium.org | 0f13e74 | 2014-01-03 15:51:11 +0000 | [diff] [blame^] | 1401 | Maybe<int> fixed_right_arg, |
| 1402 | HAllocationMode allocation_mode); |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1403 | |
machenbach@chromium.org | c1789ee | 2013-07-05 07:09:57 +0000 | [diff] [blame] | 1404 | HLoadNamedField* AddLoadFixedArrayLength(HValue *object); |
| 1405 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1406 | HValue* AddLoadJSBuiltin(Builtins::JavaScript builtin); |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1407 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1408 | HValue* EnforceNumberType(HValue* number, Handle<Type> expected); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1409 | HValue* TruncateToNumber(HValue* value, Handle<Type>* expected); |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1410 | |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1411 | void FinishExitWithHardDeoptimization(const char* reason, |
| 1412 | HBasicBlock* continuation); |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1413 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1414 | void AddIncrementCounter(StatsCounter* counter); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1415 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1416 | class IfBuilder V8_FINAL { |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1417 | public: |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1418 | explicit IfBuilder(HGraphBuilder* builder); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1419 | IfBuilder(HGraphBuilder* builder, |
| 1420 | HIfContinuation* continuation); |
| 1421 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1422 | ~IfBuilder() { |
| 1423 | if (!finished_) End(); |
| 1424 | } |
| 1425 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1426 | template<class Condition> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1427 | Condition* If(HValue *p) { |
| 1428 | Condition* compare = builder()->New<Condition>(p); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1429 | AddCompare(compare); |
| 1430 | return compare; |
| 1431 | } |
| 1432 | |
| 1433 | template<class Condition, class P2> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1434 | Condition* If(HValue* p1, P2 p2) { |
| 1435 | Condition* compare = builder()->New<Condition>(p1, p2); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1436 | AddCompare(compare); |
| 1437 | return compare; |
| 1438 | } |
| 1439 | |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1440 | template<class Condition, class P2, class P3> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1441 | Condition* If(HValue* p1, P2 p2, P3 p3) { |
| 1442 | Condition* compare = builder()->New<Condition>(p1, p2, p3); |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1443 | AddCompare(compare); |
| 1444 | return compare; |
| 1445 | } |
| 1446 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1447 | template<class Condition> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1448 | Condition* IfNot(HValue* p) { |
| 1449 | Condition* compare = If<Condition>(p); |
| 1450 | compare->Not(); |
| 1451 | return compare; |
| 1452 | } |
| 1453 | |
| 1454 | template<class Condition, class P2> |
| 1455 | Condition* IfNot(HValue* p1, P2 p2) { |
| 1456 | Condition* compare = If<Condition>(p1, p2); |
| 1457 | compare->Not(); |
| 1458 | return compare; |
| 1459 | } |
| 1460 | |
| 1461 | template<class Condition, class P2, class P3> |
| 1462 | Condition* IfNot(HValue* p1, P2 p2, P3 p3) { |
| 1463 | Condition* compare = If<Condition>(p1, p2, p3); |
| 1464 | compare->Not(); |
| 1465 | return compare; |
| 1466 | } |
| 1467 | |
| 1468 | template<class Condition> |
| 1469 | Condition* OrIf(HValue *p) { |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1470 | Or(); |
| 1471 | return If<Condition>(p); |
| 1472 | } |
| 1473 | |
| 1474 | template<class Condition, class P2> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1475 | Condition* OrIf(HValue* p1, P2 p2) { |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1476 | Or(); |
| 1477 | return If<Condition>(p1, p2); |
| 1478 | } |
| 1479 | |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1480 | template<class Condition, class P2, class P3> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1481 | Condition* OrIf(HValue* p1, P2 p2, P3 p3) { |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1482 | Or(); |
| 1483 | return If<Condition>(p1, p2, p3); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1484 | } |
| 1485 | |
| 1486 | template<class Condition> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1487 | Condition* AndIf(HValue *p) { |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1488 | And(); |
| 1489 | return If<Condition>(p); |
| 1490 | } |
| 1491 | |
| 1492 | template<class Condition, class P2> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1493 | Condition* AndIf(HValue* p1, P2 p2) { |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1494 | And(); |
| 1495 | return If<Condition>(p1, p2); |
| 1496 | } |
| 1497 | |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1498 | template<class Condition, class P2, class P3> |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1499 | Condition* AndIf(HValue* p1, P2 p2, P3 p3) { |
mstarzinger@chromium.org | e0e1b0d | 2013-07-08 08:38:06 +0000 | [diff] [blame] | 1500 | And(); |
| 1501 | return If<Condition>(p1, p2, p3); |
| 1502 | } |
| 1503 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1504 | void Or(); |
| 1505 | void And(); |
| 1506 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1507 | // Captures the current state of this IfBuilder in the specified |
| 1508 | // continuation and ends this IfBuilder. |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1509 | void CaptureContinuation(HIfContinuation* continuation); |
| 1510 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1511 | // Joins the specified continuation from this IfBuilder and ends this |
| 1512 | // IfBuilder. This appends a Goto instruction from the true branch of |
| 1513 | // this IfBuilder to the true branch of the continuation unless the |
| 1514 | // true branch of this IfBuilder is already finished. And vice versa |
| 1515 | // for the false branch. |
| 1516 | // |
| 1517 | // The basic idea is as follows: You have several nested IfBuilder's |
| 1518 | // that you want to join based on two possible outcomes (i.e. success |
| 1519 | // and failure, or whatever). You can do this easily using this method |
| 1520 | // now, for example: |
| 1521 | // |
| 1522 | // HIfContinuation cont(graph()->CreateBasicBlock(), |
| 1523 | // graph()->CreateBasicBlock()); |
| 1524 | // ... |
| 1525 | // IfBuilder if_whatever(this); |
| 1526 | // if_whatever.If<Condition>(arg); |
| 1527 | // if_whatever.Then(); |
| 1528 | // ... |
| 1529 | // if_whatever.Else(); |
| 1530 | // ... |
| 1531 | // if_whatever.JoinContinuation(&cont); |
| 1532 | // ... |
| 1533 | // IfBuilder if_something(this); |
| 1534 | // if_something.If<Condition>(arg1, arg2); |
| 1535 | // if_something.Then(); |
| 1536 | // ... |
| 1537 | // if_something.Else(); |
| 1538 | // ... |
| 1539 | // if_something.JoinContinuation(&cont); |
| 1540 | // ... |
| 1541 | // IfBuilder if_finally(this, &cont); |
| 1542 | // if_finally.Then(); |
| 1543 | // // continues after then code of if_whatever or if_something. |
| 1544 | // ... |
| 1545 | // if_finally.Else(); |
| 1546 | // // continues after else code of if_whatever or if_something. |
| 1547 | // ... |
| 1548 | // if_finally.End(); |
| 1549 | void JoinContinuation(HIfContinuation* continuation); |
| 1550 | |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1551 | void Then(); |
| 1552 | void Else(); |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1553 | void End(); |
| 1554 | |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1555 | void Deopt(const char* reason); |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame] | 1556 | void ThenDeopt(const char* reason) { |
| 1557 | Then(); |
| 1558 | Deopt(reason); |
| 1559 | } |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1560 | void ElseDeopt(const char* reason) { |
ulan@chromium.org | 32d7dba | 2013-04-24 10:59:06 +0000 | [diff] [blame] | 1561 | Else(); |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1562 | Deopt(reason); |
ulan@chromium.org | 32d7dba | 2013-04-24 10:59:06 +0000 | [diff] [blame] | 1563 | } |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1564 | |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1565 | void Return(HValue* value); |
| 1566 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1567 | private: |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1568 | HControlInstruction* AddCompare(HControlInstruction* compare); |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1569 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 1570 | HGraphBuilder* builder() const { return builder_; } |
mstarzinger@chromium.org | 71fc346 | 2013-02-27 09:34:27 +0000 | [diff] [blame] | 1571 | |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame] | 1572 | void AddMergeAtJoinBlock(bool deopt); |
| 1573 | |
| 1574 | void Finish(); |
| 1575 | void Finish(HBasicBlock** then_continuation, |
| 1576 | HBasicBlock** else_continuation); |
| 1577 | |
| 1578 | class MergeAtJoinBlock : public ZoneObject { |
| 1579 | public: |
| 1580 | MergeAtJoinBlock(HBasicBlock* block, |
| 1581 | bool deopt, |
| 1582 | MergeAtJoinBlock* next) |
| 1583 | : block_(block), |
| 1584 | deopt_(deopt), |
| 1585 | next_(next) {} |
| 1586 | HBasicBlock* block_; |
| 1587 | bool deopt_; |
| 1588 | MergeAtJoinBlock* next_; |
| 1589 | }; |
| 1590 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1591 | HGraphBuilder* builder_; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1592 | bool finished_ : 1; |
| 1593 | bool did_then_ : 1; |
| 1594 | bool did_else_ : 1; |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame] | 1595 | bool did_else_if_ : 1; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1596 | bool did_and_ : 1; |
| 1597 | bool did_or_ : 1; |
| 1598 | bool captured_ : 1; |
| 1599 | bool needs_compare_ : 1; |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame] | 1600 | bool pending_merge_block_ : 1; |
ulan@chromium.org | 09d7ab5 | 2013-02-25 15:50:35 +0000 | [diff] [blame] | 1601 | HBasicBlock* first_true_block_; |
ulan@chromium.org | 09d7ab5 | 2013-02-25 15:50:35 +0000 | [diff] [blame] | 1602 | HBasicBlock* first_false_block_; |
mstarzinger@chromium.org | b228be0 | 2013-04-18 14:56:59 +0000 | [diff] [blame] | 1603 | HBasicBlock* split_edge_merge_block_; |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame] | 1604 | MergeAtJoinBlock* merge_at_join_blocks_; |
| 1605 | int normal_merge_at_join_block_count_; |
| 1606 | int deopt_merge_at_join_block_count_; |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1607 | }; |
| 1608 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1609 | class LoopBuilder V8_FINAL { |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1610 | public: |
| 1611 | enum Direction { |
| 1612 | kPreIncrement, |
| 1613 | kPostIncrement, |
| 1614 | kPreDecrement, |
| 1615 | kPostDecrement |
| 1616 | }; |
| 1617 | |
| 1618 | LoopBuilder(HGraphBuilder* builder, |
| 1619 | HValue* context, |
danno@chromium.org | 2d18b36 | 2013-03-22 17:19:26 +0000 | [diff] [blame] | 1620 | Direction direction); |
verwaest@chromium.org | 662436e | 2013-08-28 08:41:27 +0000 | [diff] [blame] | 1621 | LoopBuilder(HGraphBuilder* builder, |
| 1622 | HValue* context, |
| 1623 | Direction direction, |
| 1624 | HValue* increment_amount); |
| 1625 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1626 | ~LoopBuilder() { |
| 1627 | ASSERT(finished_); |
| 1628 | } |
| 1629 | |
ulan@chromium.org | 09d7ab5 | 2013-02-25 15:50:35 +0000 | [diff] [blame] | 1630 | HValue* BeginBody( |
| 1631 | HValue* initial, |
| 1632 | HValue* terminating, |
ulan@chromium.org | dfe5307 | 2013-06-06 14:14:51 +0000 | [diff] [blame] | 1633 | Token::Value token); |
verwaest@chromium.org | 662436e | 2013-08-28 08:41:27 +0000 | [diff] [blame] | 1634 | |
| 1635 | void Break(); |
| 1636 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1637 | void EndBody(); |
| 1638 | |
| 1639 | private: |
mstarzinger@chromium.org | 71fc346 | 2013-02-27 09:34:27 +0000 | [diff] [blame] | 1640 | Zone* zone() { return builder_->zone(); } |
| 1641 | |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1642 | HGraphBuilder* builder_; |
| 1643 | HValue* context_; |
verwaest@chromium.org | 662436e | 2013-08-28 08:41:27 +0000 | [diff] [blame] | 1644 | HValue* increment_amount_; |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1645 | HInstruction* increment_; |
| 1646 | HPhi* phi_; |
| 1647 | HBasicBlock* header_block_; |
| 1648 | HBasicBlock* body_block_; |
| 1649 | HBasicBlock* exit_block_; |
verwaest@chromium.org | 662436e | 2013-08-28 08:41:27 +0000 | [diff] [blame] | 1650 | HBasicBlock* exit_trampoline_block_; |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1651 | Direction direction_; |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1652 | bool finished_; |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1653 | }; |
| 1654 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1655 | HValue* BuildNewElementsCapacity(HValue* old_capacity); |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1656 | |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1657 | void BuildNewSpaceArrayCheck(HValue* length, |
| 1658 | ElementsKind kind); |
| 1659 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1660 | class JSArrayBuilder V8_FINAL { |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1661 | public: |
| 1662 | JSArrayBuilder(HGraphBuilder* builder, |
| 1663 | ElementsKind kind, |
| 1664 | HValue* allocation_site_payload, |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 1665 | HValue* constructor_function, |
| 1666 | AllocationSiteOverrideMode override_mode); |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 1667 | |
| 1668 | JSArrayBuilder(HGraphBuilder* builder, |
| 1669 | ElementsKind kind, |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame] | 1670 | HValue* constructor_function = NULL); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1671 | |
machenbach@chromium.org | b5be0a9 | 2013-11-15 10:32:41 +0000 | [diff] [blame] | 1672 | enum FillMode { |
| 1673 | DONT_FILL_WITH_HOLE, |
| 1674 | FILL_WITH_HOLE |
| 1675 | }; |
| 1676 | |
| 1677 | ElementsKind kind() { return kind_; } |
| 1678 | |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1679 | HValue* AllocateEmptyArray(); |
| 1680 | HValue* AllocateArray(HValue* capacity, HValue* length_field, |
machenbach@chromium.org | b5be0a9 | 2013-11-15 10:32:41 +0000 | [diff] [blame] | 1681 | FillMode fill_mode = FILL_WITH_HOLE); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1682 | HValue* GetElementsLocation() { return elements_location_; } |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame] | 1683 | HValue* EmitMapCode(); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1684 | |
| 1685 | private: |
| 1686 | Zone* zone() const { return builder_->zone(); } |
| 1687 | int elements_size() const { |
| 1688 | return IsFastDoubleElementsKind(kind_) ? kDoubleSize : kPointerSize; |
| 1689 | } |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1690 | HGraphBuilder* builder() { return builder_; } |
| 1691 | HGraph* graph() { return builder_->graph(); } |
| 1692 | int initial_capacity() { |
| 1693 | STATIC_ASSERT(JSArray::kPreallocatedArrayElements > 0); |
| 1694 | return JSArray::kPreallocatedArrayElements; |
| 1695 | } |
| 1696 | |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 1697 | HValue* EmitInternalMapCode(); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1698 | HValue* EstablishEmptyArrayAllocationSize(); |
| 1699 | HValue* EstablishAllocationSize(HValue* length_node); |
| 1700 | HValue* AllocateArray(HValue* size_in_bytes, HValue* capacity, |
machenbach@chromium.org | b5be0a9 | 2013-11-15 10:32:41 +0000 | [diff] [blame] | 1701 | HValue* length_field, |
| 1702 | FillMode fill_mode = FILL_WITH_HOLE); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1703 | |
| 1704 | HGraphBuilder* builder_; |
| 1705 | ElementsKind kind_; |
| 1706 | AllocationSiteMode mode_; |
| 1707 | HValue* allocation_site_payload_; |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 1708 | HValue* constructor_function_; |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1709 | HInnerAllocatedObject* elements_location_; |
| 1710 | }; |
| 1711 | |
machenbach@chromium.org | b5be0a9 | 2013-11-15 10:32:41 +0000 | [diff] [blame] | 1712 | HValue* BuildAllocateArrayFromLength(JSArrayBuilder* array_builder, |
| 1713 | HValue* length_argument); |
| 1714 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1715 | HValue* BuildAllocateElements(ElementsKind kind, |
danno@chromium.org | 2d18b36 | 2013-03-22 17:19:26 +0000 | [diff] [blame] | 1716 | HValue* capacity); |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1717 | |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 1718 | void BuildInitializeElementsHeader(HValue* elements, |
| 1719 | ElementsKind kind, |
| 1720 | HValue* capacity); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 1721 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1722 | HValue* BuildAllocateElementsAndInitializeElementsHeader(ElementsKind kind, |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 1723 | HValue* capacity); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 1724 | |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1725 | // array must have been allocated with enough room for |
jkummerow@chromium.org | ba72ec8 | 2013-07-22 09:21:20 +0000 | [diff] [blame] | 1726 | // 1) the JSArray, 2) a AllocationMemento if mode requires it, |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1727 | // 3) a FixedArray or FixedDoubleArray. |
| 1728 | // A pointer to the Fixed(Double)Array is returned. |
| 1729 | HInnerAllocatedObject* BuildJSArrayHeader(HValue* array, |
| 1730 | HValue* array_map, |
| 1731 | AllocationSiteMode mode, |
jkummerow@chromium.org | fb732b1 | 2013-07-26 10:27:09 +0000 | [diff] [blame] | 1732 | ElementsKind elements_kind, |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1733 | HValue* allocation_site_payload, |
| 1734 | HValue* length_field); |
| 1735 | |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1736 | HValue* BuildGrowElementsCapacity(HValue* object, |
| 1737 | HValue* elements, |
| 1738 | ElementsKind kind, |
danno@chromium.org | bee5199 | 2013-07-10 14:57:15 +0000 | [diff] [blame] | 1739 | ElementsKind new_kind, |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1740 | HValue* length, |
danno@chromium.org | 2d18b36 | 2013-03-22 17:19:26 +0000 | [diff] [blame] | 1741 | HValue* new_capacity); |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1742 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1743 | void BuildFillElementsWithHole(HValue* elements, |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1744 | ElementsKind elements_kind, |
| 1745 | HValue* from, |
danno@chromium.org | 2d18b36 | 2013-03-22 17:19:26 +0000 | [diff] [blame] | 1746 | HValue* to); |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1747 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1748 | void BuildCopyElements(HValue* from_elements, |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1749 | ElementsKind from_elements_kind, |
| 1750 | HValue* to_elements, |
| 1751 | ElementsKind to_elements_kind, |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 1752 | HValue* length, |
danno@chromium.org | 2d18b36 | 2013-03-22 17:19:26 +0000 | [diff] [blame] | 1753 | HValue* capacity); |
danno@chromium.org | 94b0d6f | 2013-02-04 13:33:20 +0000 | [diff] [blame] | 1754 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1755 | HValue* BuildCloneShallowArray(HValue* boilerplate, |
danno@chromium.org | bee5199 | 2013-07-10 14:57:15 +0000 | [diff] [blame] | 1756 | HValue* allocation_site, |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 1757 | AllocationSiteMode mode, |
| 1758 | ElementsKind kind, |
| 1759 | int length); |
| 1760 | |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame] | 1761 | HValue* BuildElementIndexHash(HValue* index); |
| 1762 | |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1763 | void BuildCompareNil( |
| 1764 | HValue* value, |
danno@chromium.org | 4172848 | 2013-06-12 22:31:22 +0000 | [diff] [blame] | 1765 | Handle<Type> type, |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1766 | HIfContinuation* continuation); |
| 1767 | |
machenbach@chromium.org | ce9c514 | 2013-12-03 08:00:39 +0000 | [diff] [blame] | 1768 | void BuildCreateAllocationMemento(HValue* previous_object, |
| 1769 | HValue* previous_object_size, |
| 1770 | HValue* payload); |
danno@chromium.org | ca29dd8 | 2013-04-26 11:59:48 +0000 | [diff] [blame] | 1771 | |
verwaest@chromium.org | ec6855e | 2013-08-22 12:26:58 +0000 | [diff] [blame] | 1772 | HInstruction* BuildConstantMapCheck(Handle<JSObject> constant, |
| 1773 | CompilationInfo* info); |
| 1774 | HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype, |
| 1775 | Handle<JSObject> holder); |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1776 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1777 | HInstruction* BuildGetNativeContext(); |
| 1778 | HInstruction* BuildGetArrayFunction(); |
ulan@chromium.org | 57ff881 | 2013-05-10 08:16:55 +0000 | [diff] [blame] | 1779 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1780 | protected: |
| 1781 | void SetSourcePosition(int position) { |
| 1782 | ASSERT(position != RelocInfo::kNoPosition); |
| 1783 | position_ = position; |
| 1784 | } |
| 1785 | |
machenbach@chromium.org | 37be408 | 2013-11-26 13:50:38 +0000 | [diff] [blame] | 1786 | template <typename ViewClass> |
| 1787 | void BuildArrayBufferViewInitialization(HValue* obj, |
| 1788 | HValue* buffer, |
| 1789 | HValue* byte_offset, |
| 1790 | HValue* byte_length); |
| 1791 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1792 | private: |
| 1793 | HGraphBuilder(); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1794 | |
machenbach@chromium.org | ea46888 | 2013-11-18 08:53:19 +0000 | [diff] [blame] | 1795 | HValue* BuildUncheckedDictionaryElementLoadHelper( |
| 1796 | HValue* elements, |
| 1797 | HValue* key, |
| 1798 | HValue* hash, |
| 1799 | HValue* mask, |
| 1800 | int current_probe); |
| 1801 | |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1802 | void PadEnvironmentForContinuation(HBasicBlock* from, |
| 1803 | HBasicBlock* continuation); |
| 1804 | |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1805 | template <class I> |
| 1806 | I* AddInstructionTyped(I* instr) { |
| 1807 | return I::cast(AddInstruction(instr)); |
| 1808 | } |
| 1809 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1810 | CompilationInfo* info_; |
| 1811 | HGraph* graph_; |
| 1812 | HBasicBlock* current_block_; |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1813 | int position_; |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1814 | }; |
| 1815 | |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1816 | |
| 1817 | template<> |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1818 | inline HDeoptimize* HGraphBuilder::Add<HDeoptimize>( |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1819 | const char* reason, Deoptimizer::BailoutType type) { |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1820 | if (type == Deoptimizer::SOFT) { |
| 1821 | isolate()->counters()->soft_deopts_requested()->Increment(); |
| 1822 | if (FLAG_always_opt) return NULL; |
| 1823 | } |
| 1824 | if (current_block()->IsDeoptimizing()) return NULL; |
jkummerow@chromium.org | d8a3a14 | 2013-10-03 12:15:05 +0000 | [diff] [blame] | 1825 | HBasicBlock* after_deopt_block = CreateBasicBlock( |
| 1826 | current_block()->last_environment()); |
| 1827 | HDeoptimize* instr = New<HDeoptimize>(reason, type, after_deopt_block); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1828 | if (type == Deoptimizer::SOFT) { |
| 1829 | isolate()->counters()->soft_deopts_inserted()->Increment(); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1830 | } |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1831 | FinishCurrentBlock(instr); |
jkummerow@chromium.org | d8a3a14 | 2013-10-03 12:15:05 +0000 | [diff] [blame] | 1832 | set_current_block(after_deopt_block); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1833 | return instr; |
| 1834 | } |
| 1835 | |
| 1836 | |
| 1837 | template<> |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1838 | inline HInstruction* HGraphBuilder::AddUncasted<HDeoptimize>( |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 1839 | const char* reason, Deoptimizer::BailoutType type) { |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1840 | return Add<HDeoptimize>(reason, type); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1841 | } |
| 1842 | |
| 1843 | |
| 1844 | template<> |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1845 | inline HSimulate* HGraphBuilder::Add<HSimulate>( |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1846 | BailoutId id, |
| 1847 | RemovableSimulate removable) { |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1848 | HSimulate* instr = current_block()->CreateSimulate(id, removable); |
| 1849 | AddInstruction(instr); |
| 1850 | return instr; |
| 1851 | } |
| 1852 | |
| 1853 | |
| 1854 | template<> |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1855 | inline HSimulate* HGraphBuilder::Add<HSimulate>( |
| 1856 | BailoutId id) { |
| 1857 | return Add<HSimulate>(id, FIXED_SIMULATE); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1858 | } |
| 1859 | |
| 1860 | |
| 1861 | template<> |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1862 | inline HInstruction* HGraphBuilder::AddUncasted<HSimulate>(BailoutId id) { |
| 1863 | return Add<HSimulate>(id, FIXED_SIMULATE); |
| 1864 | } |
| 1865 | |
| 1866 | |
| 1867 | template<> |
| 1868 | inline HReturn* HGraphBuilder::Add<HReturn>(HValue* value) { |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1869 | int num_parameters = graph()->info()->num_parameters(); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1870 | HValue* params = AddUncasted<HConstant>(num_parameters); |
| 1871 | HReturn* return_instruction = New<HReturn>(value, params); |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1872 | FinishExitCurrentBlock(return_instruction); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1873 | return return_instruction; |
| 1874 | } |
| 1875 | |
| 1876 | |
| 1877 | template<> |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1878 | inline HReturn* HGraphBuilder::Add<HReturn>(HConstant* value) { |
| 1879 | return Add<HReturn>(static_cast<HValue*>(value)); |
| 1880 | } |
| 1881 | |
| 1882 | template<> |
| 1883 | inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HValue* value) { |
| 1884 | return Add<HReturn>(value); |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1885 | } |
| 1886 | |
| 1887 | |
| 1888 | template<> |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1889 | inline HInstruction* HGraphBuilder::AddUncasted<HReturn>(HConstant* value) { |
| 1890 | return Add<HReturn>(value); |
| 1891 | } |
| 1892 | |
| 1893 | |
| 1894 | template<> |
| 1895 | inline HCallRuntime* HGraphBuilder::Add<HCallRuntime>( |
jkummerow@chromium.org | fb7a7c4 | 2013-10-02 11:41:02 +0000 | [diff] [blame] | 1896 | Handle<String> name, |
| 1897 | const Runtime::Function* c_function, |
| 1898 | int argument_count) { |
| 1899 | HCallRuntime* instr = New<HCallRuntime>(name, c_function, argument_count); |
| 1900 | if (graph()->info()->IsStub()) { |
| 1901 | // When compiling code stubs, we don't want to save all double registers |
| 1902 | // upon entry to the stub, but instead have the call runtime instruction |
| 1903 | // save the double registers only on-demand (in the fallback case). |
| 1904 | instr->set_save_doubles(kSaveFPRegs); |
| 1905 | } |
| 1906 | AddInstruction(instr); |
| 1907 | return instr; |
| 1908 | } |
| 1909 | |
| 1910 | |
| 1911 | template<> |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1912 | inline HInstruction* HGraphBuilder::AddUncasted<HCallRuntime>( |
| 1913 | Handle<String> name, |
| 1914 | const Runtime::Function* c_function, |
| 1915 | int argument_count) { |
| 1916 | return Add<HCallRuntime>(name, c_function, argument_count); |
| 1917 | } |
| 1918 | |
| 1919 | |
| 1920 | template<> |
| 1921 | inline HContext* HGraphBuilder::New<HContext>() { |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1922 | return HContext::New(zone()); |
yangguo@chromium.org | c73d55b | 2013-07-24 08:18:28 +0000 | [diff] [blame] | 1923 | } |
| 1924 | |
| 1925 | |
machenbach@chromium.org | f984189 | 2013-11-25 12:01:13 +0000 | [diff] [blame] | 1926 | template<> |
| 1927 | inline HInstruction* HGraphBuilder::NewUncasted<HContext>() { |
| 1928 | return New<HContext>(); |
| 1929 | } |
| 1930 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 1931 | class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1932 | public: |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1933 | // A class encapsulating (lazily-allocated) break and continue blocks for |
| 1934 | // a breakable statement. Separated from BreakAndContinueScope so that it |
| 1935 | // can have a separate lifetime. |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1936 | class BreakAndContinueInfo V8_FINAL BASE_EMBEDDED { |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1937 | public: |
kmillikin@chromium.org | be6bd10 | 2012-02-23 08:45:21 +0000 | [diff] [blame] | 1938 | explicit BreakAndContinueInfo(BreakableStatement* target, |
| 1939 | int drop_extra = 0) |
| 1940 | : target_(target), |
| 1941 | break_block_(NULL), |
| 1942 | continue_block_(NULL), |
| 1943 | drop_extra_(drop_extra) { |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1944 | } |
| 1945 | |
| 1946 | BreakableStatement* target() { return target_; } |
| 1947 | HBasicBlock* break_block() { return break_block_; } |
| 1948 | void set_break_block(HBasicBlock* block) { break_block_ = block; } |
| 1949 | HBasicBlock* continue_block() { return continue_block_; } |
| 1950 | void set_continue_block(HBasicBlock* block) { continue_block_ = block; } |
kmillikin@chromium.org | be6bd10 | 2012-02-23 08:45:21 +0000 | [diff] [blame] | 1951 | int drop_extra() { return drop_extra_; } |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1952 | |
| 1953 | private: |
| 1954 | BreakableStatement* target_; |
| 1955 | HBasicBlock* break_block_; |
| 1956 | HBasicBlock* continue_block_; |
kmillikin@chromium.org | be6bd10 | 2012-02-23 08:45:21 +0000 | [diff] [blame] | 1957 | int drop_extra_; |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1958 | }; |
| 1959 | |
| 1960 | // A helper class to maintain a stack of current BreakAndContinueInfo |
| 1961 | // structures mirroring BreakableStatement nesting. |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1962 | class BreakAndContinueScope V8_FINAL BASE_EMBEDDED { |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1963 | public: |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1964 | BreakAndContinueScope(BreakAndContinueInfo* info, |
| 1965 | HOptimizedGraphBuilder* owner) |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1966 | : info_(info), owner_(owner), next_(owner->break_scope()) { |
| 1967 | owner->set_break_scope(this); |
| 1968 | } |
| 1969 | |
| 1970 | ~BreakAndContinueScope() { owner_->set_break_scope(next_); } |
| 1971 | |
| 1972 | BreakAndContinueInfo* info() { return info_; } |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1973 | HOptimizedGraphBuilder* owner() { return owner_; } |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1974 | BreakAndContinueScope* next() { return next_; } |
| 1975 | |
| 1976 | // Search the break stack for a break or continue target. |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 1977 | enum BreakType { BREAK, CONTINUE }; |
kmillikin@chromium.org | be6bd10 | 2012-02-23 08:45:21 +0000 | [diff] [blame] | 1978 | HBasicBlock* Get(BreakableStatement* stmt, BreakType type, int* drop_extra); |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1979 | |
| 1980 | private: |
| 1981 | BreakAndContinueInfo* info_; |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 1982 | HOptimizedGraphBuilder* owner_; |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1983 | BreakAndContinueScope* next_; |
| 1984 | }; |
| 1985 | |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 1986 | explicit HOptimizedGraphBuilder(CompilationInfo* info); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1987 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 1988 | virtual bool BuildGraph() V8_OVERRIDE; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 1989 | |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 1990 | // Simple accessors. |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 1991 | BreakAndContinueScope* break_scope() const { return break_scope_; } |
| 1992 | void set_break_scope(BreakAndContinueScope* head) { break_scope_ = head; } |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 1993 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 1994 | bool inline_bailout() { return inline_bailout_; } |
| 1995 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 1996 | HValue* context() { return environment()->context(); } |
| 1997 | |
jkummerow@chromium.org | c366976 | 2013-09-30 13:42:25 +0000 | [diff] [blame] | 1998 | HOsrBuilder* osr() const { return osr_; } |
| 1999 | |
danno@chromium.org | 5940060 | 2013-08-13 17:09:37 +0000 | [diff] [blame] | 2000 | void Bailout(BailoutReason reason); |
sgjesse@chromium.org | 8e8294a | 2011-05-02 14:30:53 +0000 | [diff] [blame] | 2001 | |
ricow@chromium.org | 4f693d6 | 2011-07-04 14:01:31 +0000 | [diff] [blame] | 2002 | HBasicBlock* CreateJoin(HBasicBlock* first, |
| 2003 | HBasicBlock* second, |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 2004 | BailoutId join_id); |
ricow@chromium.org | 4f693d6 | 2011-07-04 14:01:31 +0000 | [diff] [blame] | 2005 | |
erik.corry@gmail.com | 394dbcf | 2011-10-27 07:38:48 +0000 | [diff] [blame] | 2006 | FunctionState* function_state() const { return function_state_; } |
| 2007 | |
yangguo@chromium.org | 5645471 | 2012-02-16 15:33:53 +0000 | [diff] [blame] | 2008 | void VisitDeclarations(ZoneList<Declaration*>* declarations); |
| 2009 | |
verwaest@chromium.org | 178fb15 | 2012-07-18 11:21:48 +0000 | [diff] [blame] | 2010 | void* operator new(size_t size, Zone* zone) { |
| 2011 | return zone->New(static_cast<int>(size)); |
| 2012 | } |
yangguo@chromium.org | 304cc33 | 2012-07-24 07:59:48 +0000 | [diff] [blame] | 2013 | void operator delete(void* pointer, Zone* zone) { } |
| 2014 | void operator delete(void* pointer) { } |
verwaest@chromium.org | 178fb15 | 2012-07-18 11:21:48 +0000 | [diff] [blame] | 2015 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 2016 | DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
| 2017 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 2018 | protected: |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2019 | // 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] | 2020 | typedef void (HOptimizedGraphBuilder::*InlineFunctionGenerator) |
| 2021 | (CallRuntime* call); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2022 | |
| 2023 | // Forward declarations for inner scope classes. |
| 2024 | class SubgraphScope; |
| 2025 | |
| 2026 | static const InlineFunctionGenerator kInlineFunctionGenerators[]; |
| 2027 | |
| 2028 | static const int kMaxCallPolymorphism = 4; |
| 2029 | static const int kMaxLoadPolymorphism = 4; |
| 2030 | static const int kMaxStorePolymorphism = 4; |
| 2031 | |
danno@chromium.org | fa458e4 | 2012-02-01 10:48:36 +0000 | [diff] [blame] | 2032 | // Even in the 'unlimited' case we have to have some limit in order not to |
| 2033 | // overflow the stack. |
mstarzinger@chromium.org | 88d326b | 2012-04-23 12:57:22 +0000 | [diff] [blame] | 2034 | static const int kUnlimitedMaxInlinedSourceSize = 100000; |
| 2035 | static const int kUnlimitedMaxInlinedNodes = 10000; |
| 2036 | static const int kUnlimitedMaxInlinedNodesCumulative = 10000; |
danno@chromium.org | fa458e4 | 2012-02-01 10:48:36 +0000 | [diff] [blame] | 2037 | |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 2038 | // Maximum depth and total number of elements and properties for literal |
| 2039 | // graphs to be considered for fast deep-copying. |
| 2040 | static const int kMaxFastLiteralDepth = 3; |
| 2041 | static const int kMaxFastLiteralProperties = 8; |
| 2042 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2043 | // Simple accessors. |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2044 | void set_function_state(FunctionState* state) { function_state_ = state; } |
| 2045 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2046 | AstContext* ast_context() const { return ast_context_; } |
| 2047 | void set_ast_context(AstContext* context) { ast_context_ = context; } |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2048 | |
| 2049 | // Accessors forwarded to the function state. |
danno@chromium.org | 4172848 | 2013-06-12 22:31:22 +0000 | [diff] [blame] | 2050 | CompilationInfo* current_info() const { |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2051 | return function_state()->compilation_info(); |
| 2052 | } |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2053 | AstContext* call_context() const { |
| 2054 | return function_state()->call_context(); |
| 2055 | } |
| 2056 | HBasicBlock* function_return() const { |
| 2057 | return function_state()->function_return(); |
| 2058 | } |
| 2059 | TestContext* inlined_test_context() const { |
| 2060 | return function_state()->test_context(); |
| 2061 | } |
| 2062 | void ClearInlinedTestContext() { |
| 2063 | function_state()->ClearInlinedTestContext(); |
| 2064 | } |
erik.corry@gmail.com | 394dbcf | 2011-10-27 07:38:48 +0000 | [diff] [blame] | 2065 | StrictModeFlag function_strict_mode_flag() { |
mstarzinger@chromium.org | 1b3afd1 | 2011-11-29 14:28:56 +0000 | [diff] [blame] | 2066 | return function_state()->compilation_info()->is_classic_mode() |
| 2067 | ? kNonStrictMode : kStrictMode; |
karlklose@chromium.org | 44bc708 | 2011-04-11 12:33:05 +0000 | [diff] [blame] | 2068 | } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2069 | |
| 2070 | // Generators for inline runtime functions. |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 2071 | #define INLINE_FUNCTION_GENERATOR_DECLARATION(Name, argc, ressize) \ |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 2072 | void Generate##Name(CallRuntime* call); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2073 | |
| 2074 | INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION) |
| 2075 | INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION) |
| 2076 | #undef INLINE_FUNCTION_GENERATOR_DECLARATION |
| 2077 | |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 2078 | void VisitDelete(UnaryOperation* expr); |
| 2079 | void VisitVoid(UnaryOperation* expr); |
| 2080 | void VisitTypeof(UnaryOperation* expr); |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 2081 | void VisitNot(UnaryOperation* expr); |
| 2082 | |
| 2083 | void VisitComma(BinaryOperation* expr); |
erik.corry@gmail.com | d6076d9 | 2011-06-06 09:39:18 +0000 | [diff] [blame] | 2084 | void VisitLogicalExpression(BinaryOperation* expr); |
| 2085 | void VisitArithmeticExpression(BinaryOperation* expr); |
karlklose@chromium.org | 83a4728 | 2011-05-11 11:54:09 +0000 | [diff] [blame] | 2086 | |
rossberg@chromium.org | 2c067b1 | 2012-03-19 11:01:52 +0000 | [diff] [blame] | 2087 | bool PreProcessOsrEntry(IterationStatement* statement); |
jkummerow@chromium.org | ddda9e8 | 2011-07-06 11:27:02 +0000 | [diff] [blame] | 2088 | void VisitLoopBody(IterationStatement* stmt, |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 2089 | HBasicBlock* loop_entry, |
| 2090 | BreakAndContinueInfo* break_info); |
vegorov@chromium.org | 5d6c1f5 | 2011-02-28 13:13:38 +0000 | [diff] [blame] | 2091 | |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2092 | // Create a back edge in the flow graph. body_exit is the predecessor |
| 2093 | // block and loop_entry is the successor block. loop_successor is the |
| 2094 | // block where control flow exits the loop normally (e.g., via failure of |
| 2095 | // the condition) and break_block is the block where control flow breaks |
| 2096 | // from the loop. All blocks except loop_entry can be NULL. The return |
| 2097 | // value is the new successor block which is the join of loop_successor |
| 2098 | // and break_block, or NULL. |
| 2099 | HBasicBlock* CreateLoop(IterationStatement* statement, |
| 2100 | HBasicBlock* loop_entry, |
| 2101 | HBasicBlock* body_exit, |
| 2102 | HBasicBlock* loop_successor, |
| 2103 | HBasicBlock* break_block); |
| 2104 | |
jkummerow@chromium.org | c366976 | 2013-09-30 13:42:25 +0000 | [diff] [blame] | 2105 | // Build a loop entry |
| 2106 | HBasicBlock* BuildLoopEntry(); |
| 2107 | |
| 2108 | // Builds a loop entry respectful of OSR requirements |
| 2109 | HBasicBlock* BuildLoopEntry(IterationStatement* statement); |
| 2110 | |
vegorov@chromium.org | 5d6c1f5 | 2011-02-28 13:13:38 +0000 | [diff] [blame] | 2111 | HBasicBlock* JoinContinue(IterationStatement* statement, |
| 2112 | HBasicBlock* exit_block, |
| 2113 | HBasicBlock* continue_block); |
| 2114 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2115 | HValue* Top() const { return environment()->Top(); } |
| 2116 | void Drop(int n) { environment()->Drop(n); } |
| 2117 | void Bind(Variable* var, HValue* value) { environment()->Bind(var, value); } |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 2118 | bool IsEligibleForEnvironmentLivenessAnalysis(Variable* var, |
| 2119 | int index, |
| 2120 | HValue* value, |
| 2121 | HEnvironment* env) { |
| 2122 | if (!FLAG_analyze_environment_liveness) return false; |
| 2123 | // |this| and |arguments| are always live; zapping parameters isn't |
| 2124 | // safe because function.arguments can inspect them at any time. |
| 2125 | return !var->is_this() && |
| 2126 | !var->is_arguments() && |
| 2127 | !value->IsArgumentsObject() && |
| 2128 | env->is_local_index(index); |
| 2129 | } |
| 2130 | void BindIfLive(Variable* var, HValue* value) { |
| 2131 | HEnvironment* env = environment(); |
| 2132 | int index = env->IndexFor(var); |
| 2133 | env->Bind(index, value); |
| 2134 | if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { |
| 2135 | HEnvironmentMarker* bind = |
bmeurer@chromium.org | db78329 | 2013-10-23 06:51:00 +0000 | [diff] [blame] | 2136 | Add<HEnvironmentMarker>(HEnvironmentMarker::BIND, index); |
| 2137 | USE(bind); |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 2138 | #ifdef DEBUG |
| 2139 | bind->set_closure(env->closure()); |
| 2140 | #endif |
| 2141 | } |
| 2142 | } |
bmeurer@chromium.org | db78329 | 2013-10-23 06:51:00 +0000 | [diff] [blame] | 2143 | |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 2144 | HValue* LookupAndMakeLive(Variable* var) { |
| 2145 | HEnvironment* env = environment(); |
| 2146 | int index = env->IndexFor(var); |
| 2147 | HValue* value = env->Lookup(index); |
| 2148 | if (IsEligibleForEnvironmentLivenessAnalysis(var, index, value, env)) { |
| 2149 | HEnvironmentMarker* lookup = |
bmeurer@chromium.org | db78329 | 2013-10-23 06:51:00 +0000 | [diff] [blame] | 2150 | Add<HEnvironmentMarker>(HEnvironmentMarker::LOOKUP, index); |
| 2151 | USE(lookup); |
verwaest@chromium.org | d4be0f0 | 2013-06-05 13:39:03 +0000 | [diff] [blame] | 2152 | #ifdef DEBUG |
| 2153 | lookup->set_closure(env->closure()); |
| 2154 | #endif |
| 2155 | } |
| 2156 | return value; |
| 2157 | } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2158 | |
sgjesse@chromium.org | 8e8294a | 2011-05-02 14:30:53 +0000 | [diff] [blame] | 2159 | // The value of the arguments object is allowed in some but not most value |
| 2160 | // contexts. (It's allowed in all effect contexts and disallowed in all |
| 2161 | // test contexts.) |
| 2162 | void VisitForValue(Expression* expr, |
| 2163 | ArgumentsAllowedFlag flag = ARGUMENTS_NOT_ALLOWED); |
kmillikin@chromium.org | c36ce6e | 2011-04-04 08:25:31 +0000 | [diff] [blame] | 2164 | void VisitForTypeOf(Expression* expr); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2165 | void VisitForEffect(Expression* expr); |
| 2166 | void VisitForControl(Expression* expr, |
| 2167 | HBasicBlock* true_block, |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 2168 | HBasicBlock* false_block); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2169 | |
verwaest@chromium.org | 753aee4 | 2012-07-17 16:15:42 +0000 | [diff] [blame] | 2170 | // Visit an argument subexpression and emit a push to the outgoing arguments. |
| 2171 | void VisitArgument(Expression* expr); |
vegorov@chromium.org | 3cf4731 | 2011-06-29 13:20:01 +0000 | [diff] [blame] | 2172 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2173 | void VisitArgumentList(ZoneList<Expression*>* arguments); |
| 2174 | |
fschneider@chromium.org | 3a5fd78 | 2011-02-24 10:10:44 +0000 | [diff] [blame] | 2175 | // Visit a list of expressions from left to right, each in a value context. |
| 2176 | void VisitExpressions(ZoneList<Expression*>* exprs); |
| 2177 | |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 2178 | // Remove the arguments from the bailout environment and emit instructions |
| 2179 | // to push them as outgoing parameters. |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 2180 | template <class Instruction> HInstruction* PreProcessCall(Instruction* call); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2181 | |
erik.corry@gmail.com | f2038fb | 2012-01-16 11:42:08 +0000 | [diff] [blame] | 2182 | void SetUpScope(Scope* scope); |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2183 | virtual void VisitStatements(ZoneList<Statement*>* statements) V8_OVERRIDE; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2184 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2185 | #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] | 2186 | AST_NODE_LIST(DECLARE_VISIT) |
| 2187 | #undef DECLARE_VISIT |
| 2188 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 2189 | private: |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2190 | // Helpers for flow graph construction. |
kmillikin@chromium.org | c36ce6e | 2011-04-04 08:25:31 +0000 | [diff] [blame] | 2191 | enum GlobalPropertyAccess { |
| 2192 | kUseCell, |
| 2193 | kUseGeneric |
| 2194 | }; |
| 2195 | GlobalPropertyAccess LookupGlobalProperty(Variable* var, |
| 2196 | LookupResult* lookup, |
| 2197 | bool is_store); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2198 | |
jkummerow@chromium.org | 28faa98 | 2012-04-13 09:58:30 +0000 | [diff] [blame] | 2199 | void EnsureArgumentsArePushedForAccess(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2200 | bool TryArgumentsAccess(Property* expr); |
whesse@chromium.org | 4acdc2c | 2011-08-15 13:01:23 +0000 | [diff] [blame] | 2201 | |
| 2202 | // Try to optimize fun.apply(receiver, arguments) pattern. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2203 | bool TryCallApply(Call* expr); |
whesse@chromium.org | 4acdc2c | 2011-08-15 13:01:23 +0000 | [diff] [blame] | 2204 | |
jkummerow@chromium.org | 212d964 | 2012-05-11 15:02:09 +0000 | [diff] [blame] | 2205 | int InliningAstSize(Handle<JSFunction> target); |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 2206 | bool TryInline(CallKind call_kind, |
| 2207 | Handle<JSFunction> target, |
yangguo@chromium.org | 304cc33 | 2012-07-24 07:59:48 +0000 | [diff] [blame] | 2208 | int arguments_count, |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 2209 | HValue* implicit_return_value, |
| 2210 | BailoutId ast_id, |
| 2211 | BailoutId return_id, |
| 2212 | InliningKind inlining_kind); |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 2213 | |
| 2214 | bool TryInlineCall(Call* expr, bool drop_extra = false); |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 2215 | bool TryInlineConstruct(CallNew* expr, HValue* implicit_return_value); |
jkummerow@chromium.org | 3d00d0a | 2013-09-04 13:57:32 +0000 | [diff] [blame] | 2216 | bool TryInlineGetter(Handle<JSFunction> getter, |
| 2217 | BailoutId ast_id, |
| 2218 | BailoutId return_id); |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 2219 | bool TryInlineSetter(Handle<JSFunction> setter, |
danno@chromium.org | b0deb65 | 2013-06-20 16:20:19 +0000 | [diff] [blame] | 2220 | BailoutId id, |
| 2221 | BailoutId assignment_id, |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 2222 | HValue* implicit_return_value); |
ulan@chromium.org | 6ba1fd0 | 2013-02-14 14:56:11 +0000 | [diff] [blame] | 2223 | bool TryInlineApply(Handle<JSFunction> function, |
| 2224 | Call* expr, |
| 2225 | int arguments_count); |
yangguo@chromium.org | 78d1ad4 | 2012-02-09 13:53:47 +0000 | [diff] [blame] | 2226 | bool TryInlineBuiltinMethodCall(Call* expr, |
ulan@chromium.org | 967e270 | 2012-02-28 09:49:15 +0000 | [diff] [blame] | 2227 | HValue* receiver, |
| 2228 | Handle<Map> receiver_map, |
| 2229 | CheckType check_type); |
yangguo@chromium.org | 78d1ad4 | 2012-02-09 13:53:47 +0000 | [diff] [blame] | 2230 | bool TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra); |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2231 | |
| 2232 | // If --trace-inlining, print a line of the inlining trace. Inlining |
| 2233 | // succeeded if the reason string is NULL and failed if there is a |
| 2234 | // non-NULL reason string. |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 2235 | void TraceInline(Handle<JSFunction> target, |
| 2236 | Handle<JSFunction> caller, |
| 2237 | const char* failure_reason); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2238 | |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 2239 | void HandleGlobalVariableAssignment(Variable* var, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2240 | HValue* value, |
mstarzinger@chromium.org | 471f2f1 | 2012-08-10 14:46:33 +0000 | [diff] [blame] | 2241 | BailoutId ast_id); |
ager@chromium.org | 5f0c45f | 2010-12-17 08:51:21 +0000 | [diff] [blame] | 2242 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2243 | void HandlePropertyAssignment(Assignment* expr); |
| 2244 | void HandleCompoundAssignment(Assignment* expr); |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 2245 | void HandlePolymorphicLoadNamedField(BailoutId ast_id, |
jkummerow@chromium.org | 3d00d0a | 2013-09-04 13:57:32 +0000 | [diff] [blame] | 2246 | BailoutId return_id, |
jkummerow@chromium.org | 1456e70 | 2012-03-30 08:38:13 +0000 | [diff] [blame] | 2247 | HValue* object, |
| 2248 | SmallMapList* types, |
| 2249 | Handle<String> name); |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 2250 | |
machenbach@chromium.org | 37be408 | 2013-11-26 13:50:38 +0000 | [diff] [blame] | 2251 | void VisitTypedArrayInitialize(CallRuntime* expr); |
| 2252 | |
machenbach@chromium.org | b5be0a9 | 2013-11-15 10:32:41 +0000 | [diff] [blame] | 2253 | bool IsCallNewArrayInlineable(CallNew* expr); |
| 2254 | void BuildInlinedCallNewArray(CallNew* expr); |
| 2255 | |
machenbach@chromium.org | af9cfcb | 2013-11-19 11:05:18 +0000 | [diff] [blame] | 2256 | void VisitDataViewInitialize(CallRuntime* expr); |
| 2257 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 2258 | class PropertyAccessInfo { |
| 2259 | public: |
| 2260 | PropertyAccessInfo(Isolate* isolate, Handle<Map> map, Handle<String> name) |
| 2261 | : lookup_(isolate), |
| 2262 | map_(map), |
| 2263 | name_(name), |
| 2264 | access_(HObjectAccess::ForMap()) { } |
| 2265 | |
| 2266 | // Checkes whether this PropertyAccessInfo can be handled as a monomorphic |
| 2267 | // load named. It additionally fills in the fields necessary to generate the |
| 2268 | // lookup code. |
| 2269 | bool CanLoadMonomorphic(); |
| 2270 | |
| 2271 | // Checks whether all types behave uniform when loading name. If all maps |
| 2272 | // behave the same, a single monomorphic load instruction can be emitted, |
| 2273 | // guarded by a single map-checks instruction that whether the receiver is |
| 2274 | // an instance of any of the types. |
| 2275 | // This method skips the first type in types, assuming that this |
| 2276 | // PropertyAccessInfo is built for types->first(). |
| 2277 | bool CanLoadAsMonomorphic(SmallMapList* types); |
| 2278 | |
machenbach@chromium.org | 8e36b5b | 2013-09-26 07:36:30 +0000 | [diff] [blame] | 2279 | bool IsJSObjectFieldAccessor() { |
| 2280 | int offset; // unused |
| 2281 | return Accessors::IsJSObjectFieldAccessor(map_, name_, &offset); |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 2282 | } |
| 2283 | |
machenbach@chromium.org | 8e36b5b | 2013-09-26 07:36:30 +0000 | [diff] [blame] | 2284 | bool GetJSObjectFieldAccess(HObjectAccess* access) { |
| 2285 | if (IsStringLength()) { |
| 2286 | *access = HObjectAccess::ForStringLength(); |
| 2287 | return true; |
| 2288 | } else if (IsArrayLength()) { |
| 2289 | *access = HObjectAccess::ForArrayLength(map_->elements_kind()); |
| 2290 | return true; |
| 2291 | } else { |
| 2292 | int offset; |
| 2293 | if (Accessors::IsJSObjectFieldAccessor(map_, name_, &offset)) { |
| 2294 | *access = HObjectAccess::ForJSObjectOffset(offset); |
| 2295 | return true; |
| 2296 | } |
| 2297 | return false; |
| 2298 | } |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 2299 | } |
| 2300 | |
| 2301 | bool has_holder() { return !holder_.is_null(); } |
| 2302 | |
| 2303 | LookupResult* lookup() { return &lookup_; } |
| 2304 | Handle<Map> map() { return map_; } |
| 2305 | Handle<JSObject> holder() { return holder_; } |
| 2306 | Handle<JSFunction> accessor() { return accessor_; } |
| 2307 | Handle<Object> constant() { return constant_; } |
| 2308 | HObjectAccess access() { return access_; } |
| 2309 | |
| 2310 | private: |
| 2311 | Isolate* isolate() { return lookup_.isolate(); } |
| 2312 | |
machenbach@chromium.org | 8e36b5b | 2013-09-26 07:36:30 +0000 | [diff] [blame] | 2313 | bool IsStringLength() { |
| 2314 | return map_->instance_type() < FIRST_NONSTRING_TYPE && |
| 2315 | name_->Equals(isolate()->heap()->length_string()); |
| 2316 | } |
| 2317 | |
| 2318 | bool IsArrayLength() { |
| 2319 | return map_->instance_type() == JS_ARRAY_TYPE && |
| 2320 | name_->Equals(isolate()->heap()->length_string()); |
| 2321 | } |
| 2322 | |
machenbach@chromium.org | 528ce02 | 2013-09-23 14:09:36 +0000 | [diff] [blame] | 2323 | bool LoadResult(Handle<Map> map); |
| 2324 | bool LookupDescriptor(); |
| 2325 | bool LookupInPrototypes(); |
| 2326 | bool IsCompatibleForLoad(PropertyAccessInfo* other); |
| 2327 | |
| 2328 | void GeneralizeRepresentation(Representation r) { |
| 2329 | access_ = access_.WithRepresentation( |
| 2330 | access_.representation().generalize(r)); |
| 2331 | } |
| 2332 | |
| 2333 | LookupResult lookup_; |
| 2334 | Handle<Map> map_; |
| 2335 | Handle<String> name_; |
| 2336 | Handle<JSObject> holder_; |
| 2337 | Handle<JSFunction> accessor_; |
| 2338 | Handle<Object> constant_; |
| 2339 | HObjectAccess access_; |
| 2340 | }; |
| 2341 | |
| 2342 | HInstruction* BuildLoadMonomorphic(PropertyAccessInfo* info, |
| 2343 | HValue* object, |
| 2344 | HInstruction* checked_object, |
| 2345 | BailoutId ast_id, |
| 2346 | BailoutId return_id, |
| 2347 | bool can_inline_accessor = true); |
| 2348 | |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 2349 | void HandlePolymorphicStoreNamedField(BailoutId assignment_id, |
danno@chromium.org | fe57867 | 2013-06-15 14:38:35 +0000 | [diff] [blame] | 2350 | HValue* object, |
dslomov@chromium.org | b752d40 | 2013-06-18 11:54:54 +0000 | [diff] [blame] | 2351 | HValue* value, |
danno@chromium.org | fe57867 | 2013-06-15 14:38:35 +0000 | [diff] [blame] | 2352 | SmallMapList* types, |
| 2353 | Handle<String> name); |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 2354 | bool TryStorePolymorphicAsMonomorphic(BailoutId assignment_id, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2355 | HValue* object, |
| 2356 | HValue* value, |
ricow@chromium.org | ddd545c | 2011-08-24 12:02:41 +0000 | [diff] [blame] | 2357 | SmallMapList* types, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2358 | Handle<String> name); |
| 2359 | void HandlePolymorphicCallNamed(Call* expr, |
| 2360 | HValue* receiver, |
ricow@chromium.org | ddd545c | 2011-08-24 12:02:41 +0000 | [diff] [blame] | 2361 | SmallMapList* types, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2362 | Handle<String> name); |
danno@chromium.org | bee5199 | 2013-07-10 14:57:15 +0000 | [diff] [blame] | 2363 | bool TryCallPolymorphicAsMonomorphic(Call* expr, |
| 2364 | HValue* receiver, |
| 2365 | SmallMapList* types, |
| 2366 | Handle<String> name); |
erik.corry@gmail.com | c3b670f | 2011-10-05 21:44:48 +0000 | [diff] [blame] | 2367 | void HandleLiteralCompareTypeof(CompareOperation* expr, |
jkummerow@chromium.org | 96a3c51 | 2013-07-18 17:02:47 +0000 | [diff] [blame] | 2368 | Expression* sub_expr, |
ager@chromium.org | 04921a8 | 2011-06-27 13:21:41 +0000 | [diff] [blame] | 2369 | Handle<String> check); |
erik.corry@gmail.com | c3b670f | 2011-10-05 21:44:48 +0000 | [diff] [blame] | 2370 | void HandleLiteralCompareNil(CompareOperation* expr, |
jkummerow@chromium.org | 96a3c51 | 2013-07-18 17:02:47 +0000 | [diff] [blame] | 2371 | Expression* sub_expr, |
erik.corry@gmail.com | c3b670f | 2011-10-05 21:44:48 +0000 | [diff] [blame] | 2372 | NilValue nil); |
hpayer@chromium.org | 4f99be9 | 2013-12-18 16:23:55 +0000 | [diff] [blame] | 2373 | HControlInstruction* BuildCompareInstruction(Token::Value op, |
| 2374 | HValue* left, |
| 2375 | HValue* right, |
| 2376 | Handle<Type> left_type, |
| 2377 | Handle<Type> right_type, |
| 2378 | Handle<Type> combined_type, |
| 2379 | int left_position, |
| 2380 | int right_position, |
| 2381 | BailoutId bailout_id); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2382 | |
danno@chromium.org | d3c4210 | 2013-08-01 16:58:23 +0000 | [diff] [blame] | 2383 | HInstruction* BuildStringCharCodeAt(HValue* string, |
ulan@chromium.org | 2e04b58 | 2013-02-21 14:06:02 +0000 | [diff] [blame] | 2384 | HValue* index); |
machenbach@chromium.org | 7ff7607 | 2013-11-21 09:47:43 +0000 | [diff] [blame] | 2385 | HValue* BuildBinaryOperation(BinaryOperation* expr, |
| 2386 | HValue* left, |
| 2387 | HValue* right); |
kmillikin@chromium.org | c53e10d | 2011-05-18 09:12:58 +0000 | [diff] [blame] | 2388 | HInstruction* BuildIncrement(bool returns_original_input, |
sgjesse@chromium.org | 8e8294a | 2011-05-02 14:30:53 +0000 | [diff] [blame] | 2389 | CountOperation* expr); |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 2390 | HInstruction* BuildLoadKeyedGeneric(HValue* object, |
| 2391 | HValue* key); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2392 | |
mstarzinger@chromium.org | c6d9cee | 2012-07-03 10:03:19 +0000 | [diff] [blame] | 2393 | HInstruction* TryBuildConsolidatedElementLoad(HValue* object, |
| 2394 | HValue* key, |
| 2395 | HValue* val, |
| 2396 | SmallMapList* maps); |
| 2397 | |
jkummerow@chromium.org | 1e8da74 | 2013-08-26 17:13:35 +0000 | [diff] [blame] | 2398 | LoadKeyedHoleMode BuildKeyedHoleMode(Handle<Map> map); |
| 2399 | |
whesse@chromium.org | 7b26015 | 2011-06-20 15:33:18 +0000 | [diff] [blame] | 2400 | HInstruction* BuildMonomorphicElementAccess(HValue* object, |
| 2401 | HValue* key, |
| 2402 | HValue* val, |
svenpanne@chromium.org | 830d30c | 2012-05-29 13:20:14 +0000 | [diff] [blame] | 2403 | HValue* dependency, |
erik.corry@gmail.com | 394dbcf | 2011-10-27 07:38:48 +0000 | [diff] [blame] | 2404 | Handle<Map> map, |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 2405 | bool is_store, |
| 2406 | KeyedAccessStoreMode store_mode); |
mstarzinger@chromium.org | c6d9cee | 2012-07-03 10:03:19 +0000 | [diff] [blame] | 2407 | |
whesse@chromium.org | 7b26015 | 2011-06-20 15:33:18 +0000 | [diff] [blame] | 2408 | HValue* HandlePolymorphicElementAccess(HValue* object, |
| 2409 | HValue* key, |
| 2410 | HValue* val, |
dslomov@chromium.org | 4a35c5a | 2013-09-13 07:28:52 +0000 | [diff] [blame] | 2411 | SmallMapList* maps, |
whesse@chromium.org | 7b26015 | 2011-06-20 15:33:18 +0000 | [diff] [blame] | 2412 | bool is_store, |
jkummerow@chromium.org | 7bd87f0 | 2013-03-20 18:06:29 +0000 | [diff] [blame] | 2413 | KeyedAccessStoreMode store_mode, |
whesse@chromium.org | 7b26015 | 2011-06-20 15:33:18 +0000 | [diff] [blame] | 2414 | bool* has_side_effects); |
| 2415 | |
| 2416 | HValue* HandleKeyedElementAccess(HValue* obj, |
| 2417 | HValue* key, |
| 2418 | HValue* val, |
| 2419 | Expression* expr, |
whesse@chromium.org | 7b26015 | 2011-06-20 15:33:18 +0000 | [diff] [blame] | 2420 | bool is_store, |
| 2421 | bool* has_side_effects); |
karlklose@chromium.org | 44bc708 | 2011-04-11 12:33:05 +0000 | [diff] [blame] | 2422 | |
ulan@chromium.org | ea52b5f | 2012-07-30 13:05:33 +0000 | [diff] [blame] | 2423 | HInstruction* BuildLoadNamedGeneric(HValue* object, |
| 2424 | Handle<String> name, |
| 2425 | Property* expr); |
ulan@chromium.org | ea52b5f | 2012-07-30 13:05:33 +0000 | [diff] [blame] | 2426 | |
verwaest@chromium.org | 003a925 | 2013-08-12 17:15:20 +0000 | [diff] [blame] | 2427 | HCheckMaps* AddCheckMap(HValue* object, Handle<Map> map); |
mstarzinger@chromium.org | f705b50 | 2013-04-04 11:38:09 +0000 | [diff] [blame] | 2428 | |
jkummerow@chromium.org | 3d00d0a | 2013-09-04 13:57:32 +0000 | [diff] [blame] | 2429 | void BuildLoad(Property* property, |
jkummerow@chromium.org | 3d00d0a | 2013-09-04 13:57:32 +0000 | [diff] [blame] | 2430 | BailoutId ast_id); |
| 2431 | void PushLoad(Property* property, |
| 2432 | HValue* object, |
bmeurer@chromium.org | 71f9fca | 2013-10-22 08:00:09 +0000 | [diff] [blame] | 2433 | HValue* key); |
jkummerow@chromium.org | 3d00d0a | 2013-09-04 13:57:32 +0000 | [diff] [blame] | 2434 | |
dslomov@chromium.org | 639bac0 | 2013-09-09 11:58:54 +0000 | [diff] [blame] | 2435 | void BuildStoreForEffect(Expression* expression, |
| 2436 | Property* prop, |
| 2437 | BailoutId ast_id, |
| 2438 | BailoutId return_id, |
| 2439 | HValue* object, |
| 2440 | HValue* key, |
| 2441 | HValue* value); |
jkummerow@chromium.org | 2c9426b | 2013-09-05 16:31:13 +0000 | [diff] [blame] | 2442 | |
dslomov@chromium.org | 639bac0 | 2013-09-09 11:58:54 +0000 | [diff] [blame] | 2443 | void BuildStore(Expression* expression, |
| 2444 | Property* prop, |
| 2445 | BailoutId ast_id, |
| 2446 | BailoutId return_id, |
| 2447 | bool is_uninitialized = false); |
danno@chromium.org | b0deb65 | 2013-06-20 16:20:19 +0000 | [diff] [blame] | 2448 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2449 | HInstruction* BuildStoreNamedField(HValue* object, |
| 2450 | Handle<String> name, |
| 2451 | HValue* value, |
verwaest@chromium.org | b6d052d | 2012-07-27 08:03:27 +0000 | [diff] [blame] | 2452 | Handle<Map> map, |
verwaest@chromium.org | e4ee6de | 2012-11-06 12:13:00 +0000 | [diff] [blame] | 2453 | LookupResult* lookup); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2454 | HInstruction* BuildStoreNamedGeneric(HValue* object, |
| 2455 | Handle<String> name, |
| 2456 | HValue* value); |
ulan@chromium.org | ea52b5f | 2012-07-30 13:05:33 +0000 | [diff] [blame] | 2457 | HInstruction* BuildStoreNamedMonomorphic(HValue* object, |
| 2458 | Handle<String> name, |
| 2459 | HValue* value, |
| 2460 | Handle<Map> map); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2461 | HInstruction* BuildStoreKeyedGeneric(HValue* object, |
| 2462 | HValue* key, |
| 2463 | HValue* value); |
| 2464 | |
ricow@chromium.org | 83aa549 | 2011-02-07 12:42:56 +0000 | [diff] [blame] | 2465 | HValue* BuildContextChainWalk(Variable* var); |
| 2466 | |
yangguo@chromium.org | 5a11aaf | 2012-06-20 11:29:00 +0000 | [diff] [blame] | 2467 | HInstruction* BuildThisFunction(); |
| 2468 | |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 2469 | HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object, |
machenbach@chromium.org | 37be408 | 2013-11-26 13:50:38 +0000 | [diff] [blame] | 2470 | AllocationSiteUsageContext* site_context); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 2471 | |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2472 | void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object, |
| 2473 | HInstruction* object); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 2474 | |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2475 | void BuildInitElementsInObjectHeader(Handle<JSObject> boilerplate_object, |
| 2476 | HInstruction* object, |
| 2477 | HInstruction* object_elements); |
mstarzinger@chromium.org | e27d617 | 2013-04-17 11:51:44 +0000 | [diff] [blame] | 2478 | |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 2479 | void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object, |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 2480 | HInstruction* object, |
machenbach@chromium.org | c86e8c2 | 2013-11-27 15:11:04 +0000 | [diff] [blame] | 2481 | AllocationSiteUsageContext* site_context, |
| 2482 | PretenureFlag pretenure_flag); |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 2483 | |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2484 | void BuildEmitElements(Handle<JSObject> boilerplate_object, |
| 2485 | Handle<FixedArrayBase> elements, |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 2486 | HValue* object_elements, |
machenbach@chromium.org | 37be408 | 2013-11-26 13:50:38 +0000 | [diff] [blame] | 2487 | AllocationSiteUsageContext* site_context); |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 2488 | |
| 2489 | void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements, |
| 2490 | ElementsKind kind, |
| 2491 | HValue* object_elements); |
| 2492 | |
| 2493 | void BuildEmitFixedArray(Handle<FixedArrayBase> elements, |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 2494 | ElementsKind kind, |
mstarzinger@chromium.org | b4968be | 2013-10-16 09:00:56 +0000 | [diff] [blame] | 2495 | HValue* object_elements, |
machenbach@chromium.org | 37be408 | 2013-11-26 13:50:38 +0000 | [diff] [blame] | 2496 | AllocationSiteUsageContext* site_context); |
jkummerow@chromium.org | c118402 | 2013-05-28 16:58:15 +0000 | [diff] [blame] | 2497 | |
verwaest@chromium.org | e4ee6de | 2012-11-06 12:13:00 +0000 | [diff] [blame] | 2498 | void AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 2499 | Handle<Map> receiver_map); |
| 2500 | |
yangguo@chromium.org | 99aa490 | 2012-07-06 16:21:55 +0000 | [diff] [blame] | 2501 | void AddCheckConstantFunction(Handle<JSObject> holder, |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2502 | HValue* receiver, |
verwaest@chromium.org | e4ee6de | 2012-11-06 12:13:00 +0000 | [diff] [blame] | 2503 | Handle<Map> receiver_map); |
| 2504 | |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2505 | // The translation state of the currently-being-translated function. |
| 2506 | FunctionState* function_state_; |
| 2507 | |
| 2508 | // The base of the function state stack. |
| 2509 | FunctionState initial_function_state_; |
| 2510 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2511 | // Expression context of the currently visited subexpression. NULL when |
| 2512 | // visiting statements. |
| 2513 | AstContext* ast_context_; |
| 2514 | |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2515 | // A stack of breakable statements entered. |
| 2516 | BreakAndContinueScope* break_scope_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2517 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2518 | int inlined_count_; |
erik.corry@gmail.com | ed49e96 | 2012-04-17 11:57:53 +0000 | [diff] [blame] | 2519 | ZoneList<Handle<Object> > globals_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2520 | |
ager@chromium.org | ea91cc5 | 2011-05-23 06:06:11 +0000 | [diff] [blame] | 2521 | bool inline_bailout_; |
| 2522 | |
machenbach@chromium.org | c1789ee | 2013-07-05 07:09:57 +0000 | [diff] [blame] | 2523 | HOsrBuilder* osr_; |
| 2524 | |
karlklose@chromium.org | 8f806e8 | 2011-03-07 14:06:08 +0000 | [diff] [blame] | 2525 | friend class FunctionState; // Pushes and pops the state stack. |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2526 | friend class AstContext; // Pushes and pops the AST context stack. |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 2527 | friend class KeyedLoadFastElementStub; |
machenbach@chromium.org | c1789ee | 2013-07-05 07:09:57 +0000 | [diff] [blame] | 2528 | friend class HOsrBuilder; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2529 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 2530 | DISALLOW_COPY_AND_ASSIGN(HOptimizedGraphBuilder); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2531 | }; |
| 2532 | |
| 2533 | |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 2534 | Zone* AstContext::zone() const { return owner_->zone(); } |
vegorov@chromium.org | 74f333b | 2011-04-06 11:17:46 +0000 | [diff] [blame] | 2535 | |
| 2536 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2537 | class HStatistics V8_FINAL: public Malloced { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2538 | public: |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 2539 | HStatistics() |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2540 | : times_(5), |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 2541 | names_(5), |
| 2542 | sizes_(5), |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 2543 | total_size_(0), |
whesse@chromium.org | b08986c | 2011-03-14 16:13:42 +0000 | [diff] [blame] | 2544 | source_size_(0) { } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2545 | |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2546 | void Initialize(CompilationInfo* info); |
| 2547 | void Print(); |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2548 | void SaveTiming(const char* name, TimeDelta time, unsigned size); |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2549 | |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2550 | void IncrementFullCodeGen(TimeDelta full_code_gen) { |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2551 | full_code_gen_ += full_code_gen; |
| 2552 | } |
| 2553 | |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2554 | void IncrementSubtotals(TimeDelta create_graph, |
| 2555 | TimeDelta optimize_graph, |
| 2556 | TimeDelta generate_code) { |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2557 | create_graph_ += create_graph; |
| 2558 | optimize_graph_ += optimize_graph; |
| 2559 | generate_code_ += generate_code; |
| 2560 | } |
| 2561 | |
| 2562 | private: |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2563 | List<TimeDelta> times_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2564 | List<const char*> names_; |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 2565 | List<unsigned> sizes_; |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2566 | TimeDelta create_graph_; |
| 2567 | TimeDelta optimize_graph_; |
| 2568 | TimeDelta generate_code_; |
sgjesse@chromium.org | c6c5718 | 2011-01-17 12:24:25 +0000 | [diff] [blame] | 2569 | unsigned total_size_; |
jkummerow@chromium.org | dc94e19 | 2013-08-30 11:35:42 +0000 | [diff] [blame] | 2570 | TimeDelta full_code_gen_; |
whesse@chromium.org | b08986c | 2011-03-14 16:13:42 +0000 | [diff] [blame] | 2571 | double source_size_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2572 | }; |
| 2573 | |
| 2574 | |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2575 | class HPhase : public CompilationPhase { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2576 | public: |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2577 | HPhase(const char* name, HGraph* graph) |
| 2578 | : CompilationPhase(name, graph->info()), |
| 2579 | graph_(graph) { } |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2580 | ~HPhase(); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2581 | |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2582 | protected: |
| 2583 | HGraph* graph() const { return graph_; } |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2584 | |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2585 | private: |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2586 | HGraph* graph_; |
mstarzinger@chromium.org | 1510d58 | 2013-06-28 14:00:48 +0000 | [diff] [blame] | 2587 | |
| 2588 | DISALLOW_COPY_AND_ASSIGN(HPhase); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2589 | }; |
| 2590 | |
| 2591 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2592 | class HTracer V8_FINAL : public Malloced { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2593 | public: |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2594 | explicit HTracer(int isolate_id) |
| 2595 | : trace_(&string_allocator_), indent_(0) { |
jkummerow@chromium.org | fb732b1 | 2013-07-26 10:27:09 +0000 | [diff] [blame] | 2596 | if (FLAG_trace_hydrogen_file == NULL) { |
| 2597 | OS::SNPrintF(filename_, |
| 2598 | "hydrogen-%d-%d.cfg", |
| 2599 | OS::GetCurrentProcessId(), |
| 2600 | isolate_id); |
| 2601 | } else { |
| 2602 | OS::StrNCpy(filename_, FLAG_trace_hydrogen_file, filename_.length()); |
| 2603 | } |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2604 | WriteChars(filename_.start(), "", 0, false); |
| 2605 | } |
| 2606 | |
yangguo@chromium.org | a6bbcc8 | 2012-12-21 12:35:02 +0000 | [diff] [blame] | 2607 | void TraceCompilation(CompilationInfo* info); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2608 | void TraceHydrogen(const char* name, HGraph* graph); |
jkummerow@chromium.org | 28583c9 | 2012-07-16 11:31:55 +0000 | [diff] [blame] | 2609 | void TraceLithium(const char* name, LChunk* chunk); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2610 | void TraceLiveRanges(const char* name, LAllocator* allocator); |
| 2611 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2612 | private: |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2613 | class Tag V8_FINAL BASE_EMBEDDED { |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2614 | public: |
| 2615 | Tag(HTracer* tracer, const char* name) { |
| 2616 | name_ = name; |
| 2617 | tracer_ = tracer; |
| 2618 | tracer->PrintIndent(); |
| 2619 | tracer->trace_.Add("begin_%s\n", name); |
| 2620 | tracer->indent_++; |
| 2621 | } |
| 2622 | |
| 2623 | ~Tag() { |
| 2624 | tracer_->indent_--; |
| 2625 | tracer_->PrintIndent(); |
| 2626 | tracer_->trace_.Add("end_%s\n", name_); |
| 2627 | ASSERT(tracer_->indent_ >= 0); |
| 2628 | tracer_->FlushToFile(); |
| 2629 | } |
| 2630 | |
| 2631 | private: |
| 2632 | HTracer* tracer_; |
| 2633 | const char* name_; |
| 2634 | }; |
| 2635 | |
mmassi@chromium.org | 7028c05 | 2012-06-13 11:51:58 +0000 | [diff] [blame] | 2636 | void TraceLiveRange(LiveRange* range, const char* type, Zone* zone); |
jkummerow@chromium.org | 28583c9 | 2012-07-16 11:31:55 +0000 | [diff] [blame] | 2637 | void Trace(const char* name, HGraph* graph, LChunk* chunk); |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2638 | void FlushToFile(); |
| 2639 | |
| 2640 | void PrintEmptyProperty(const char* name) { |
| 2641 | PrintIndent(); |
| 2642 | trace_.Add("%s\n", name); |
| 2643 | } |
| 2644 | |
| 2645 | void PrintStringProperty(const char* name, const char* value) { |
| 2646 | PrintIndent(); |
| 2647 | trace_.Add("%s \"%s\"\n", name, value); |
| 2648 | } |
| 2649 | |
| 2650 | void PrintLongProperty(const char* name, int64_t value) { |
| 2651 | PrintIndent(); |
| 2652 | trace_.Add("%s %d000\n", name, static_cast<int>(value / 1000)); |
| 2653 | } |
| 2654 | |
| 2655 | void PrintBlockProperty(const char* name, int block_id) { |
| 2656 | PrintIndent(); |
| 2657 | trace_.Add("%s \"B%d\"\n", name, block_id); |
| 2658 | } |
| 2659 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2660 | void PrintIntProperty(const char* name, int value) { |
| 2661 | PrintIndent(); |
| 2662 | trace_.Add("%s %d\n", name, value); |
| 2663 | } |
| 2664 | |
| 2665 | void PrintIndent() { |
| 2666 | for (int i = 0; i < indent_; i++) { |
| 2667 | trace_.Add(" "); |
| 2668 | } |
| 2669 | } |
| 2670 | |
ulan@chromium.org | 750145a | 2013-03-07 15:14:13 +0000 | [diff] [blame] | 2671 | EmbeddedVector<char, 64> filename_; |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2672 | HeapStringAllocator string_allocator_; |
| 2673 | StringStream trace_; |
| 2674 | int indent_; |
| 2675 | }; |
| 2676 | |
| 2677 | |
verwaest@chromium.org | 32cb9b2 | 2013-08-21 11:18:12 +0000 | [diff] [blame] | 2678 | class NoObservableSideEffectsScope V8_FINAL { |
danno@chromium.org | ad75d6f | 2013-08-12 16:57:59 +0000 | [diff] [blame] | 2679 | public: |
| 2680 | explicit NoObservableSideEffectsScope(HGraphBuilder* builder) : |
| 2681 | builder_(builder) { |
| 2682 | builder_->graph()->IncrementInNoSideEffectsScope(); |
| 2683 | } |
| 2684 | ~NoObservableSideEffectsScope() { |
| 2685 | builder_->graph()->DecrementInNoSideEffectsScope(); |
| 2686 | } |
| 2687 | |
| 2688 | private: |
| 2689 | HGraphBuilder* builder_; |
| 2690 | }; |
| 2691 | |
| 2692 | |
kasperl@chromium.org | a555126 | 2010-12-07 12:49:48 +0000 | [diff] [blame] | 2693 | } } // namespace v8::internal |
| 2694 | |
| 2695 | #endif // V8_HYDROGEN_H_ |