| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_COMPILER_AST_GRAPH_BUILDER_H_ | 5 #ifndef V8_COMPILER_AST_GRAPH_BUILDER_H_ |
| 6 #define V8_COMPILER_AST_GRAPH_BUILDER_H_ | 6 #define V8_COMPILER_AST_GRAPH_BUILDER_H_ |
| 7 | 7 |
| 8 #include "src/v8.h" | 8 #include "src/v8.h" |
| 9 | 9 |
| 10 #include "src/ast.h" | 10 #include "src/ast.h" |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 void VisitNot(UnaryOperation* expr); | 164 void VisitNot(UnaryOperation* expr); |
| 165 | 165 |
| 166 // Dispatched from VisitBinaryOperation. | 166 // Dispatched from VisitBinaryOperation. |
| 167 void VisitComma(BinaryOperation* expr); | 167 void VisitComma(BinaryOperation* expr); |
| 168 void VisitLogicalExpression(BinaryOperation* expr); | 168 void VisitLogicalExpression(BinaryOperation* expr); |
| 169 void VisitArithmeticExpression(BinaryOperation* expr); | 169 void VisitArithmeticExpression(BinaryOperation* expr); |
| 170 | 170 |
| 171 // Dispatched from VisitForInStatement. | 171 // Dispatched from VisitForInStatement. |
| 172 void VisitForInAssignment(Expression* expr, Node* value); | 172 void VisitForInAssignment(Expression* expr, Node* value); |
| 173 | 173 |
| 174 void BuildLazyBailout(Node* node, BailoutId ast_id); | 174 // Flag that describes how to combine the current environment with |
| 175 void BuildLazyBailoutWithPushedNode(Node* node, BailoutId ast_id); | 175 // the output of a node to obtain a framestate for lazy bailout. |
| 176 enum OutputFrameStateCombine { |
| 177 PUSH_OUTPUT, // Push the output on the expression stack. |
| 178 IGNORE_OUTPUT // Use the frame state as-is. |
| 179 }; |
| 180 |
| 181 // Builds deoptimization for a given node. |
| 182 void PrepareFrameState(Node* node, BailoutId ast_id, |
| 183 OutputFrameStateCombine combine = IGNORE_OUTPUT); |
| 184 |
| 185 OutputFrameStateCombine StateCombineFromAstContext(); |
| 176 | 186 |
| 177 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 187 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
| 178 DISALLOW_COPY_AND_ASSIGN(AstGraphBuilder); | 188 DISALLOW_COPY_AND_ASSIGN(AstGraphBuilder); |
| 179 }; | 189 }; |
| 180 | 190 |
| 181 | 191 |
| 182 // The abstract execution environment for generated code consists of | 192 // The abstract execution environment for generated code consists of |
| 183 // parameter variables, local variables and the operand stack. The | 193 // parameter variables, local variables and the operand stack. The |
| 184 // environment will perform proper SSA-renaming of all tracked nodes | 194 // environment will perform proper SSA-renaming of all tracked nodes |
| 185 // at split and merge points in the control flow. Internally all the | 195 // at split and merge points in the control flow. Internally all the |
| (...skipping 13 matching lines...) Expand all Loading... |
| 199 return static_cast<int>(values()->size()) - parameters_count_ - | 209 return static_cast<int>(values()->size()) - parameters_count_ - |
| 200 locals_count_; | 210 locals_count_; |
| 201 } | 211 } |
| 202 | 212 |
| 203 // Operations on parameter or local variables. The parameter indices are | 213 // Operations on parameter or local variables. The parameter indices are |
| 204 // shifted by 1 (receiver is parameter index -1 but environment index 0). | 214 // shifted by 1 (receiver is parameter index -1 but environment index 0). |
| 205 void Bind(Variable* variable, Node* node) { | 215 void Bind(Variable* variable, Node* node) { |
| 206 DCHECK(variable->IsStackAllocated()); | 216 DCHECK(variable->IsStackAllocated()); |
| 207 if (variable->IsParameter()) { | 217 if (variable->IsParameter()) { |
| 208 values()->at(variable->index() + 1) = node; | 218 values()->at(variable->index() + 1) = node; |
| 209 parameters_dirty_ = true; | |
| 210 } else { | 219 } else { |
| 211 DCHECK(variable->IsStackLocal()); | 220 DCHECK(variable->IsStackLocal()); |
| 212 values()->at(variable->index() + parameters_count_) = node; | 221 values()->at(variable->index() + parameters_count_) = node; |
| 213 locals_dirty_ = true; | |
| 214 } | 222 } |
| 215 } | 223 } |
| 216 Node* Lookup(Variable* variable) { | 224 Node* Lookup(Variable* variable) { |
| 217 DCHECK(variable->IsStackAllocated()); | 225 DCHECK(variable->IsStackAllocated()); |
| 218 if (variable->IsParameter()) { | 226 if (variable->IsParameter()) { |
| 219 return values()->at(variable->index() + 1); | 227 return values()->at(variable->index() + 1); |
| 220 } else { | 228 } else { |
| 221 DCHECK(variable->IsStackLocal()); | 229 DCHECK(variable->IsStackLocal()); |
| 222 return values()->at(variable->index() + parameters_count_); | 230 return values()->at(variable->index() + parameters_count_); |
| 223 } | 231 } |
| 224 } | 232 } |
| 225 | 233 |
| 226 // Operations on the operand stack. | 234 // Operations on the operand stack. |
| 227 void Push(Node* node) { | 235 void Push(Node* node) { |
| 228 values()->push_back(node); | 236 values()->push_back(node); |
| 229 stack_dirty_ = true; | |
| 230 } | 237 } |
| 231 Node* Top() { | 238 Node* Top() { |
| 232 DCHECK(stack_height() > 0); | 239 DCHECK(stack_height() > 0); |
| 233 return values()->back(); | 240 return values()->back(); |
| 234 } | 241 } |
| 235 Node* Pop() { | 242 Node* Pop() { |
| 236 DCHECK(stack_height() > 0); | 243 DCHECK(stack_height() > 0); |
| 237 Node* back = values()->back(); | 244 Node* back = values()->back(); |
| 238 values()->pop_back(); | 245 values()->pop_back(); |
| 239 stack_dirty_ = true; | |
| 240 return back; | 246 return back; |
| 241 } | 247 } |
| 242 | 248 |
| 243 // Direct mutations of the operand stack. | 249 // Direct mutations of the operand stack. |
| 244 void Poke(int depth, Node* node) { | 250 void Poke(int depth, Node* node) { |
| 245 DCHECK(depth >= 0 && depth < stack_height()); | 251 DCHECK(depth >= 0 && depth < stack_height()); |
| 246 int index = static_cast<int>(values()->size()) - depth - 1; | 252 int index = static_cast<int>(values()->size()) - depth - 1; |
| 247 values()->at(index) = node; | 253 values()->at(index) = node; |
| 248 stack_dirty_ = true; | |
| 249 } | 254 } |
| 250 Node* Peek(int depth) { | 255 Node* Peek(int depth) { |
| 251 DCHECK(depth >= 0 && depth < stack_height()); | 256 DCHECK(depth >= 0 && depth < stack_height()); |
| 252 int index = static_cast<int>(values()->size()) - depth - 1; | 257 int index = static_cast<int>(values()->size()) - depth - 1; |
| 253 return values()->at(index); | 258 return values()->at(index); |
| 254 } | 259 } |
| 255 void Drop(int depth) { | 260 void Drop(int depth) { |
| 256 DCHECK(depth >= 0 && depth <= stack_height()); | 261 DCHECK(depth >= 0 && depth <= stack_height()); |
| 257 values()->erase(values()->end() - depth, values()->end()); | 262 values()->erase(values()->end() - depth, values()->end()); |
| 258 stack_dirty_ = true; | |
| 259 } | 263 } |
| 260 | 264 |
| 261 // Preserve a checkpoint of the environment for the IR graph. Any | 265 // Preserve a checkpoint of the environment for the IR graph. Any |
| 262 // further mutation of the environment will not affect checkpoints. | 266 // further mutation of the environment will not affect checkpoints. |
| 263 Node* Checkpoint(BailoutId ast_id); | 267 Node* Checkpoint(BailoutId ast_id); |
| 264 | 268 |
| 265 private: | 269 private: |
| 270 void UpdateStateValues(Node** state_values, int offset, int count); |
| 271 |
| 266 int parameters_count_; | 272 int parameters_count_; |
| 267 int locals_count_; | 273 int locals_count_; |
| 268 Node* parameters_node_; | 274 Node* parameters_node_; |
| 269 Node* locals_node_; | 275 Node* locals_node_; |
| 270 Node* stack_node_; | 276 Node* stack_node_; |
| 271 bool parameters_dirty_; | |
| 272 bool locals_dirty_; | |
| 273 bool stack_dirty_; | |
| 274 }; | 277 }; |
| 275 | 278 |
| 276 | 279 |
| 277 // Each expression in the AST is evaluated in a specific context. This context | 280 // Each expression in the AST is evaluated in a specific context. This context |
| 278 // decides how the evaluation result is passed up the visitor. | 281 // decides how the evaluation result is passed up the visitor. |
| 279 class AstGraphBuilder::AstContext BASE_EMBEDDED { | 282 class AstGraphBuilder::AstContext BASE_EMBEDDED { |
| 280 public: | 283 public: |
| 281 bool IsEffect() const { return kind_ == Expression::kEffect; } | 284 bool IsEffect() const { return kind_ == Expression::kEffect; } |
| 282 bool IsValue() const { return kind_ == Expression::kValue; } | 285 bool IsValue() const { return kind_ == Expression::kValue; } |
| 283 bool IsTest() const { return kind_ == Expression::kTest; } | 286 bool IsTest() const { return kind_ == Expression::kTest; } |
| 284 | 287 |
| 288 // Determines how to combine the frame state with the value |
| 289 // that is about to be plugged into this AstContext. |
| 290 AstGraphBuilder::OutputFrameStateCombine GetStateCombine() { |
| 291 return IsEffect() ? IGNORE_OUTPUT : PUSH_OUTPUT; |
| 292 } |
| 293 |
| 285 // Plug a node into this expression context. Call this function in tail | 294 // Plug a node into this expression context. Call this function in tail |
| 286 // position in the Visit functions for expressions. | 295 // position in the Visit functions for expressions. |
| 287 virtual void ProduceValue(Node* value) = 0; | 296 virtual void ProduceValue(Node* value) = 0; |
| 288 virtual void ProduceValueWithLazyBailout(Node* value) = 0; | |
| 289 | 297 |
| 290 // Unplugs a node from this expression context. Call this to retrieve the | 298 // Unplugs a node from this expression context. Call this to retrieve the |
| 291 // result of another Visit function that already plugged the context. | 299 // result of another Visit function that already plugged the context. |
| 292 virtual Node* ConsumeValue() = 0; | 300 virtual Node* ConsumeValue() = 0; |
| 293 | 301 |
| 294 // Shortcut for "context->ProduceValue(context->ConsumeValue())". | 302 // Shortcut for "context->ProduceValue(context->ConsumeValue())". |
| 295 void ReplaceValue() { ProduceValue(ConsumeValue()); } | 303 void ReplaceValue() { ProduceValue(ConsumeValue()); } |
| 296 | 304 |
| 297 protected: | 305 protected: |
| 298 AstContext(AstGraphBuilder* owner, Expression::Context kind, | 306 AstContext(AstGraphBuilder* owner, Expression::Context kind); |
| 299 BailoutId bailout_id); | |
| 300 virtual ~AstContext(); | 307 virtual ~AstContext(); |
| 301 | 308 |
| 302 AstGraphBuilder* owner() const { return owner_; } | 309 AstGraphBuilder* owner() const { return owner_; } |
| 303 Environment* environment() const { return owner_->environment(); } | 310 Environment* environment() const { return owner_->environment(); } |
| 304 | 311 |
| 305 // We want to be able to assert, in a context-specific way, that the stack | 312 // We want to be able to assert, in a context-specific way, that the stack |
| 306 // height makes sense when the context is filled. | 313 // height makes sense when the context is filled. |
| 307 #ifdef DEBUG | 314 #ifdef DEBUG |
| 308 int original_height_; | 315 int original_height_; |
| 309 #endif | 316 #endif |
| 310 | 317 |
| 311 BailoutId bailout_id_; | |
| 312 | |
| 313 private: | 318 private: |
| 314 Expression::Context kind_; | 319 Expression::Context kind_; |
| 315 AstGraphBuilder* owner_; | 320 AstGraphBuilder* owner_; |
| 316 AstContext* outer_; | 321 AstContext* outer_; |
| 317 }; | 322 }; |
| 318 | 323 |
| 319 | 324 |
| 320 // Context to evaluate expression for its side effects only. | 325 // Context to evaluate expression for its side effects only. |
| 321 class AstGraphBuilder::AstEffectContext V8_FINAL : public AstContext { | 326 class AstGraphBuilder::AstEffectContext V8_FINAL : public AstContext { |
| 322 public: | 327 public: |
| 323 explicit AstEffectContext(AstGraphBuilder* owner, BailoutId bailout_id) | 328 explicit AstEffectContext(AstGraphBuilder* owner) |
| 324 : AstContext(owner, Expression::kEffect, bailout_id) {} | 329 : AstContext(owner, Expression::kEffect) {} |
| 325 virtual ~AstEffectContext(); | 330 virtual ~AstEffectContext(); |
| 326 virtual void ProduceValue(Node* value) V8_OVERRIDE; | 331 virtual void ProduceValue(Node* value) V8_OVERRIDE; |
| 327 virtual void ProduceValueWithLazyBailout(Node* value) V8_OVERRIDE; | |
| 328 virtual Node* ConsumeValue() V8_OVERRIDE; | 332 virtual Node* ConsumeValue() V8_OVERRIDE; |
| 329 }; | 333 }; |
| 330 | 334 |
| 331 | 335 |
| 332 // Context to evaluate expression for its value (and side effects). | 336 // Context to evaluate expression for its value (and side effects). |
| 333 class AstGraphBuilder::AstValueContext V8_FINAL : public AstContext { | 337 class AstGraphBuilder::AstValueContext V8_FINAL : public AstContext { |
| 334 public: | 338 public: |
| 335 explicit AstValueContext(AstGraphBuilder* owner, BailoutId bailout_id) | 339 explicit AstValueContext(AstGraphBuilder* owner) |
| 336 : AstContext(owner, Expression::kValue, bailout_id) {} | 340 : AstContext(owner, Expression::kValue) {} |
| 337 virtual ~AstValueContext(); | 341 virtual ~AstValueContext(); |
| 338 virtual void ProduceValue(Node* value) V8_OVERRIDE; | 342 virtual void ProduceValue(Node* value) V8_OVERRIDE; |
| 339 virtual void ProduceValueWithLazyBailout(Node* value) V8_OVERRIDE; | |
| 340 virtual Node* ConsumeValue() V8_OVERRIDE; | 343 virtual Node* ConsumeValue() V8_OVERRIDE; |
| 341 }; | 344 }; |
| 342 | 345 |
| 343 | 346 |
| 344 // Context to evaluate expression for a condition value (and side effects). | 347 // Context to evaluate expression for a condition value (and side effects). |
| 345 class AstGraphBuilder::AstTestContext V8_FINAL : public AstContext { | 348 class AstGraphBuilder::AstTestContext V8_FINAL : public AstContext { |
| 346 public: | 349 public: |
| 347 explicit AstTestContext(AstGraphBuilder* owner, BailoutId bailout_id) | 350 explicit AstTestContext(AstGraphBuilder* owner) |
| 348 : AstContext(owner, Expression::kTest, bailout_id) {} | 351 : AstContext(owner, Expression::kTest) {} |
| 349 virtual ~AstTestContext(); | 352 virtual ~AstTestContext(); |
| 350 virtual void ProduceValue(Node* value) V8_OVERRIDE; | 353 virtual void ProduceValue(Node* value) V8_OVERRIDE; |
| 351 virtual void ProduceValueWithLazyBailout(Node* value) V8_OVERRIDE; | |
| 352 virtual Node* ConsumeValue() V8_OVERRIDE; | 354 virtual Node* ConsumeValue() V8_OVERRIDE; |
| 353 }; | 355 }; |
| 354 | 356 |
| 355 | 357 |
| 356 // Scoped class tracking breakable statements entered by the visitor. Allows to | 358 // Scoped class tracking breakable statements entered by the visitor. Allows to |
| 357 // properly 'break' and 'continue' iteration statements as well as to 'break' | 359 // properly 'break' and 'continue' iteration statements as well as to 'break' |
| 358 // from blocks within switch statements. | 360 // from blocks within switch statements. |
| 359 class AstGraphBuilder::BreakableScope BASE_EMBEDDED { | 361 class AstGraphBuilder::BreakableScope BASE_EMBEDDED { |
| 360 public: | 362 public: |
| 361 BreakableScope(AstGraphBuilder* owner, BreakableStatement* target, | 363 BreakableScope(AstGraphBuilder* owner, BreakableStatement* target, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 }; | 421 }; |
| 420 | 422 |
| 421 Scope* AstGraphBuilder::current_scope() const { | 423 Scope* AstGraphBuilder::current_scope() const { |
| 422 return execution_context_->scope(); | 424 return execution_context_->scope(); |
| 423 } | 425 } |
| 424 } | 426 } |
| 425 } | 427 } |
| 426 } // namespace v8::internal::compiler | 428 } // namespace v8::internal::compiler |
| 427 | 429 |
| 428 #endif // V8_COMPILER_AST_GRAPH_BUILDER_H_ | 430 #endif // V8_COMPILER_AST_GRAPH_BUILDER_H_ |
| OLD | NEW |