OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_FULL_CODEGEN_FULL_CODEGEN_H_ | 5 #ifndef V8_FULL_CODEGEN_FULL_CODEGEN_H_ |
6 #define V8_FULL_CODEGEN_FULL_CODEGEN_H_ | 6 #define V8_FULL_CODEGEN_FULL_CODEGEN_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/assert-scope.h" | 9 #include "src/assert-scope.h" |
10 #include "src/ast/ast.h" | 10 #include "src/ast/ast.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 static const int kCodeSizeMultiplier = 149; | 92 static const int kCodeSizeMultiplier = 149; |
93 #elif V8_TARGET_ARCH_MIPS64 | 93 #elif V8_TARGET_ARCH_MIPS64 |
94 static const int kCodeSizeMultiplier = 149; | 94 static const int kCodeSizeMultiplier = 149; |
95 #else | 95 #else |
96 #error Unsupported target architecture. | 96 #error Unsupported target architecture. |
97 #endif | 97 #endif |
98 | 98 |
99 private: | 99 private: |
100 class Breakable; | 100 class Breakable; |
101 class Iteration; | 101 class Iteration; |
| 102 class TryFinally; |
102 | 103 |
103 class TestContext; | 104 class TestContext; |
104 | 105 |
105 class NestedStatement BASE_EMBEDDED { | 106 class NestedStatement BASE_EMBEDDED { |
106 public: | 107 public: |
107 explicit NestedStatement(FullCodeGenerator* codegen) : codegen_(codegen) { | 108 explicit NestedStatement(FullCodeGenerator* codegen) : codegen_(codegen) { |
108 // Link into codegen's nesting stack. | 109 // Link into codegen's nesting stack. |
109 previous_ = codegen->nesting_stack_; | 110 previous_ = codegen->nesting_stack_; |
110 codegen->nesting_stack_ = this; | 111 codegen->nesting_stack_ = this; |
111 } | 112 } |
112 virtual ~NestedStatement() { | 113 virtual ~NestedStatement() { |
113 // Unlink from codegen's nesting stack. | 114 // Unlink from codegen's nesting stack. |
114 DCHECK_EQ(this, codegen_->nesting_stack_); | 115 DCHECK_EQ(this, codegen_->nesting_stack_); |
115 codegen_->nesting_stack_ = previous_; | 116 codegen_->nesting_stack_ = previous_; |
116 } | 117 } |
117 | 118 |
118 virtual Breakable* AsBreakable() { return NULL; } | 119 virtual Breakable* AsBreakable() { return nullptr; } |
119 virtual Iteration* AsIteration() { return NULL; } | 120 virtual Iteration* AsIteration() { return nullptr; } |
| 121 virtual TryFinally* AsTryFinally() { return nullptr; } |
120 | 122 |
121 virtual bool IsContinueTarget(Statement* target) { return false; } | 123 virtual bool IsContinueTarget(Statement* target) { return false; } |
122 virtual bool IsBreakTarget(Statement* target) { return false; } | 124 virtual bool IsBreakTarget(Statement* target) { return false; } |
| 125 virtual bool IsTryFinally() { return false; } |
123 | 126 |
124 // Notify the statement that we are exiting it via break, continue, or | 127 // Notify the statement that we are exiting it via break, continue, or |
125 // return and give it a chance to generate cleanup code. Return the | 128 // return and give it a chance to generate cleanup code. Return the |
126 // next outer statement in the nesting stack. We accumulate in | 129 // next outer statement in the nesting stack. We accumulate in |
127 // *stack_depth the amount to drop the stack and in *context_length the | 130 // *stack_depth the amount to drop the stack and in *context_length the |
128 // number of context chain links to unwind as we traverse the nesting | 131 // number of context chain links to unwind as we traverse the nesting |
129 // stack from an exit to its target. | 132 // stack from an exit to its target. |
130 virtual NestedStatement* Exit(int* stack_depth, int* context_length) { | 133 virtual NestedStatement* Exit(int* stack_depth, int* context_length) { |
131 return previous_; | 134 return previous_; |
132 } | 135 } |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 NestedStatement* Exit(int* stack_depth, int* context_length) override { | 213 NestedStatement* Exit(int* stack_depth, int* context_length) override { |
211 *stack_depth += kElementCount; | 214 *stack_depth += kElementCount; |
212 return previous_; | 215 return previous_; |
213 } | 216 } |
214 NestedStatement* AccumulateDepth(int* stack_depth) override { | 217 NestedStatement* AccumulateDepth(int* stack_depth) override { |
215 *stack_depth += kElementCount; | 218 *stack_depth += kElementCount; |
216 return previous_; | 219 return previous_; |
217 } | 220 } |
218 }; | 221 }; |
219 | 222 |
| 223 class DeferredCommands { |
| 224 public: |
| 225 enum Command { kReturn, kThrow, kBreak, kContinue }; |
| 226 typedef int TokenId; |
| 227 struct DeferredCommand { |
| 228 Command command; |
| 229 TokenId token; |
| 230 Statement* target; |
| 231 }; |
| 232 |
| 233 DeferredCommands(FullCodeGenerator* codegen, Label* finally_entry) |
| 234 : codegen_(codegen), |
| 235 commands_(codegen->zone()), |
| 236 return_token_(TokenDispenserForFinally::kInvalidToken), |
| 237 throw_token_(TokenDispenserForFinally::kInvalidToken), |
| 238 finally_entry_(finally_entry) {} |
| 239 |
| 240 void EmitCommands(); |
| 241 |
| 242 void RecordBreak(Statement* target); |
| 243 void RecordContinue(Statement* target); |
| 244 void RecordReturn(); |
| 245 void RecordThrow(); |
| 246 void EmitFallThrough(); |
| 247 |
| 248 private: |
| 249 MacroAssembler* masm() { return codegen_->masm(); } |
| 250 void EmitJumpToFinally(TokenId token); |
| 251 |
| 252 FullCodeGenerator* codegen_; |
| 253 ZoneVector<DeferredCommand> commands_; |
| 254 TokenDispenserForFinally dispenser_; |
| 255 TokenId return_token_; |
| 256 TokenId throw_token_; |
| 257 Label* finally_entry_; |
| 258 }; |
| 259 |
220 // The try block of a try/finally statement. | 260 // The try block of a try/finally statement. |
221 class TryFinally : public NestedStatement { | 261 class TryFinally : public NestedStatement { |
222 public: | 262 public: |
223 static const int kElementCount = TryBlockConstant::kElementCount; | 263 static const int kElementCount = TryBlockConstant::kElementCount; |
224 | 264 |
225 TryFinally(FullCodeGenerator* codegen, Label* finally_entry) | 265 TryFinally(FullCodeGenerator* codegen, DeferredCommands* commands) |
226 : NestedStatement(codegen), finally_entry_(finally_entry) { | 266 : NestedStatement(codegen), deferred_commands_(commands) {} |
227 } | |
228 | 267 |
229 NestedStatement* Exit(int* stack_depth, int* context_length) override; | 268 NestedStatement* Exit(int* stack_depth, int* context_length) override; |
230 NestedStatement* AccumulateDepth(int* stack_depth) override { | 269 NestedStatement* AccumulateDepth(int* stack_depth) override { |
231 *stack_depth += kElementCount; | 270 *stack_depth += kElementCount; |
232 return previous_; | 271 return previous_; |
233 } | 272 } |
234 | 273 |
| 274 bool IsTryFinally() override { return true; } |
| 275 TryFinally* AsTryFinally() override { return this; } |
| 276 |
| 277 DeferredCommands* deferred_commands() { return deferred_commands_; } |
| 278 |
235 private: | 279 private: |
236 Label* finally_entry_; | 280 DeferredCommands* deferred_commands_; |
237 }; | 281 }; |
238 | 282 |
239 // The finally block of a try/finally statement. | 283 // The finally block of a try/finally statement. |
240 class Finally : public NestedStatement { | 284 class Finally : public NestedStatement { |
241 public: | 285 public: |
242 static const int kElementCount = 3; | 286 static const int kElementCount = 3; |
243 | 287 |
244 explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) {} | 288 explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) {} |
245 | 289 |
246 NestedStatement* Exit(int* stack_depth, int* context_length) override { | 290 NestedStatement* Exit(int* stack_depth, int* context_length) override { |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 void RecordBackEdge(BailoutId osr_ast_id); | 492 void RecordBackEdge(BailoutId osr_ast_id); |
449 // Emit a table of back edge ids, pcs and loop depths into the code stream. | 493 // Emit a table of back edge ids, pcs and loop depths into the code stream. |
450 // Return the offset of the start of the table. | 494 // Return the offset of the start of the table. |
451 unsigned EmitBackEdgeTable(); | 495 unsigned EmitBackEdgeTable(); |
452 | 496 |
453 void EmitProfilingCounterDecrement(int delta); | 497 void EmitProfilingCounterDecrement(int delta); |
454 void EmitProfilingCounterReset(); | 498 void EmitProfilingCounterReset(); |
455 | 499 |
456 // Emit code to pop values from the stack associated with nested statements | 500 // Emit code to pop values from the stack associated with nested statements |
457 // like try/catch, try/finally, etc, running the finallies and unwinding the | 501 // like try/catch, try/finally, etc, running the finallies and unwinding the |
458 // handlers as needed. | 502 // handlers as needed. Also emits the return sequence if necessary (i.e., |
459 void EmitUnwindBeforeReturn(); | 503 // if the return is not delayed by a finally block). |
| 504 void EmitUnwindAndReturn(); |
460 | 505 |
461 // Platform-specific return sequence | 506 // Platform-specific return sequence |
462 void EmitReturnSequence(); | 507 void EmitReturnSequence(); |
463 | 508 |
464 // Platform-specific code sequences for calls | 509 // Platform-specific code sequences for calls |
465 void EmitCall(Call* expr, ConvertReceiverMode = ConvertReceiverMode::kAny); | 510 void EmitCall(Call* expr, ConvertReceiverMode = ConvertReceiverMode::kAny); |
466 void EmitSuperConstructorCall(Call* expr); | 511 void EmitSuperConstructorCall(Call* expr); |
467 void EmitCallWithLoadIC(Call* expr); | 512 void EmitCallWithLoadIC(Call* expr); |
468 void EmitSuperCallWithLoadIC(Call* expr); | 513 void EmitSuperCallWithLoadIC(Call* expr); |
469 void EmitKeyedCallWithLoadIC(Call* expr, Expression* key); | 514 void EmitKeyedCallWithLoadIC(Call* expr, Expression* key); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 SetCallPosition(expr); | 707 SetCallPosition(expr); |
663 } | 708 } |
664 | 709 |
665 // Non-local control flow support. | 710 // Non-local control flow support. |
666 void EnterTryBlock(int handler_index, Label* handler); | 711 void EnterTryBlock(int handler_index, Label* handler); |
667 void ExitTryBlock(int handler_index); | 712 void ExitTryBlock(int handler_index); |
668 void EnterFinallyBlock(); | 713 void EnterFinallyBlock(); |
669 void ExitFinallyBlock(); | 714 void ExitFinallyBlock(); |
670 void ClearPendingMessage(); | 715 void ClearPendingMessage(); |
671 | 716 |
| 717 void EmitContinue(Statement* target); |
| 718 void EmitBreak(Statement* target); |
| 719 |
672 // Loop nesting counter. | 720 // Loop nesting counter. |
673 int loop_depth() { return loop_depth_; } | 721 int loop_depth() { return loop_depth_; } |
674 void increment_loop_depth() { loop_depth_++; } | 722 void increment_loop_depth() { loop_depth_++; } |
675 void decrement_loop_depth() { | 723 void decrement_loop_depth() { |
676 DCHECK(loop_depth_ > 0); | 724 DCHECK(loop_depth_ > 0); |
677 loop_depth_--; | 725 loop_depth_--; |
678 } | 726 } |
679 | 727 |
680 MacroAssembler* masm() const { return masm_; } | 728 MacroAssembler* masm() const { return masm_; } |
681 | 729 |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1043 Address start_; | 1091 Address start_; |
1044 Address instruction_start_; | 1092 Address instruction_start_; |
1045 uint32_t length_; | 1093 uint32_t length_; |
1046 }; | 1094 }; |
1047 | 1095 |
1048 | 1096 |
1049 } // namespace internal | 1097 } // namespace internal |
1050 } // namespace v8 | 1098 } // namespace v8 |
1051 | 1099 |
1052 #endif // V8_FULL_CODEGEN_FULL_CODEGEN_H_ | 1100 #endif // V8_FULL_CODEGEN_FULL_CODEGEN_H_ |
OLD | NEW |