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 24 matching lines...) Expand all Loading... |
35 | 35 |
36 FullCodeGenerator(MacroAssembler* masm, CompilationInfo* info) | 36 FullCodeGenerator(MacroAssembler* masm, CompilationInfo* info) |
37 : masm_(masm), | 37 : masm_(masm), |
38 info_(info), | 38 info_(info), |
39 isolate_(info->isolate()), | 39 isolate_(info->isolate()), |
40 zone_(info->zone()), | 40 zone_(info->zone()), |
41 scope_(info->scope()), | 41 scope_(info->scope()), |
42 nesting_stack_(NULL), | 42 nesting_stack_(NULL), |
43 loop_depth_(0), | 43 loop_depth_(0), |
44 try_catch_depth_(0), | 44 try_catch_depth_(0), |
| 45 operand_stack_depth_(0), |
45 globals_(NULL), | 46 globals_(NULL), |
46 context_(NULL), | 47 context_(NULL), |
47 bailout_entries_(info->HasDeoptimizationSupport() | 48 bailout_entries_(info->HasDeoptimizationSupport() |
48 ? info->literal()->ast_node_count() | 49 ? info->literal()->ast_node_count() |
49 : 0, | 50 : 0, |
50 info->zone()), | 51 info->zone()), |
51 back_edges_(2, info->zone()), | 52 back_edges_(2, info->zone()), |
52 handler_table_(info->zone()), | 53 handler_table_(info->zone()), |
53 ic_total_count_(0) { | 54 ic_total_count_(0) { |
54 DCHECK(!info->IsStub()); | 55 DCHECK(!info->IsStub()); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 // Notify the statement that we are exiting it via break, continue, or | 130 // Notify the statement that we are exiting it via break, continue, or |
130 // return and give it a chance to generate cleanup code. Return the | 131 // return and give it a chance to generate cleanup code. Return the |
131 // next outer statement in the nesting stack. We accumulate in | 132 // next outer statement in the nesting stack. We accumulate in |
132 // *stack_depth the amount to drop the stack and in *context_length the | 133 // *stack_depth the amount to drop the stack and in *context_length the |
133 // number of context chain links to unwind as we traverse the nesting | 134 // number of context chain links to unwind as we traverse the nesting |
134 // stack from an exit to its target. | 135 // stack from an exit to its target. |
135 virtual NestedStatement* Exit(int* stack_depth, int* context_length) { | 136 virtual NestedStatement* Exit(int* stack_depth, int* context_length) { |
136 return previous_; | 137 return previous_; |
137 } | 138 } |
138 | 139 |
139 // Like the Exit() method above, but limited to accumulating stack depth. | |
140 virtual NestedStatement* AccumulateDepth(int* stack_depth) { | |
141 return previous_; | |
142 } | |
143 | |
144 protected: | 140 protected: |
145 MacroAssembler* masm() { return codegen_->masm(); } | 141 MacroAssembler* masm() { return codegen_->masm(); } |
146 | 142 |
147 FullCodeGenerator* codegen_; | 143 FullCodeGenerator* codegen_; |
148 NestedStatement* previous_; | 144 NestedStatement* previous_; |
149 | 145 |
150 private: | 146 private: |
151 DISALLOW_COPY_AND_ASSIGN(NestedStatement); | 147 DISALLOW_COPY_AND_ASSIGN(NestedStatement); |
152 }; | 148 }; |
153 | 149 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 class TryCatch : public NestedStatement { | 205 class TryCatch : public NestedStatement { |
210 public: | 206 public: |
211 static const int kElementCount = TryBlockConstant::kElementCount; | 207 static const int kElementCount = TryBlockConstant::kElementCount; |
212 | 208 |
213 explicit TryCatch(FullCodeGenerator* codegen) : NestedStatement(codegen) {} | 209 explicit TryCatch(FullCodeGenerator* codegen) : NestedStatement(codegen) {} |
214 | 210 |
215 NestedStatement* Exit(int* stack_depth, int* context_length) override { | 211 NestedStatement* Exit(int* stack_depth, int* context_length) override { |
216 *stack_depth += kElementCount; | 212 *stack_depth += kElementCount; |
217 return previous_; | 213 return previous_; |
218 } | 214 } |
219 NestedStatement* AccumulateDepth(int* stack_depth) override { | |
220 *stack_depth += kElementCount; | |
221 return previous_; | |
222 } | |
223 }; | 215 }; |
224 | 216 |
225 class DeferredCommands { | 217 class DeferredCommands { |
226 public: | 218 public: |
227 enum Command { kReturn, kThrow, kBreak, kContinue }; | 219 enum Command { kReturn, kThrow, kBreak, kContinue }; |
228 typedef int TokenId; | 220 typedef int TokenId; |
229 struct DeferredCommand { | 221 struct DeferredCommand { |
230 Command command; | 222 Command command; |
231 TokenId token; | 223 TokenId token; |
232 Statement* target; | 224 Statement* target; |
(...skipping 28 matching lines...) Expand all Loading... |
261 | 253 |
262 // The try block of a try/finally statement. | 254 // The try block of a try/finally statement. |
263 class TryFinally : public NestedStatement { | 255 class TryFinally : public NestedStatement { |
264 public: | 256 public: |
265 static const int kElementCount = TryBlockConstant::kElementCount; | 257 static const int kElementCount = TryBlockConstant::kElementCount; |
266 | 258 |
267 TryFinally(FullCodeGenerator* codegen, DeferredCommands* commands) | 259 TryFinally(FullCodeGenerator* codegen, DeferredCommands* commands) |
268 : NestedStatement(codegen), deferred_commands_(commands) {} | 260 : NestedStatement(codegen), deferred_commands_(commands) {} |
269 | 261 |
270 NestedStatement* Exit(int* stack_depth, int* context_length) override; | 262 NestedStatement* Exit(int* stack_depth, int* context_length) override; |
271 NestedStatement* AccumulateDepth(int* stack_depth) override { | |
272 *stack_depth += kElementCount; | |
273 return previous_; | |
274 } | |
275 | 263 |
276 bool IsTryFinally() override { return true; } | 264 bool IsTryFinally() override { return true; } |
277 TryFinally* AsTryFinally() override { return this; } | 265 TryFinally* AsTryFinally() override { return this; } |
278 | 266 |
279 DeferredCommands* deferred_commands() { return deferred_commands_; } | 267 DeferredCommands* deferred_commands() { return deferred_commands_; } |
280 | 268 |
281 private: | 269 private: |
282 DeferredCommands* deferred_commands_; | 270 DeferredCommands* deferred_commands_; |
283 }; | 271 }; |
284 | 272 |
285 // The finally block of a try/finally statement. | 273 // The finally block of a try/finally statement. |
286 class Finally : public NestedStatement { | 274 class Finally : public NestedStatement { |
287 public: | 275 public: |
288 static const int kElementCount = 3; | 276 static const int kElementCount = 3; |
289 | 277 |
290 explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) {} | 278 explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) {} |
291 | 279 |
292 NestedStatement* Exit(int* stack_depth, int* context_length) override { | 280 NestedStatement* Exit(int* stack_depth, int* context_length) override { |
293 *stack_depth += kElementCount; | 281 *stack_depth += kElementCount; |
294 return previous_; | 282 return previous_; |
295 } | 283 } |
296 NestedStatement* AccumulateDepth(int* stack_depth) override { | |
297 *stack_depth += kElementCount; | |
298 return previous_; | |
299 } | |
300 }; | 284 }; |
301 | 285 |
302 // The body of a for/in loop. | 286 // The body of a for/in loop. |
303 class ForIn : public Iteration { | 287 class ForIn : public Iteration { |
304 public: | 288 public: |
305 static const int kElementCount = 5; | 289 static const int kElementCount = 5; |
306 | 290 |
307 ForIn(FullCodeGenerator* codegen, ForInStatement* statement) | 291 ForIn(FullCodeGenerator* codegen, ForInStatement* statement) |
308 : Iteration(codegen, statement) { | 292 : Iteration(codegen, statement) { |
309 } | 293 } |
310 | 294 |
311 NestedStatement* Exit(int* stack_depth, int* context_length) override { | 295 NestedStatement* Exit(int* stack_depth, int* context_length) override { |
312 *stack_depth += kElementCount; | 296 *stack_depth += kElementCount; |
313 return previous_; | 297 return previous_; |
314 } | 298 } |
315 NestedStatement* AccumulateDepth(int* stack_depth) override { | |
316 *stack_depth += kElementCount; | |
317 return previous_; | |
318 } | |
319 }; | 299 }; |
320 | 300 |
321 | 301 |
322 // The body of a with or catch. | 302 // The body of a with or catch. |
323 class WithOrCatch : public NestedStatement { | 303 class WithOrCatch : public NestedStatement { |
324 public: | 304 public: |
325 explicit WithOrCatch(FullCodeGenerator* codegen) | 305 explicit WithOrCatch(FullCodeGenerator* codegen) |
326 : NestedStatement(codegen) { | 306 : NestedStatement(codegen) { |
327 } | 307 } |
328 | 308 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 // variable. Writing does not need the write barrier. | 373 // variable. Writing does not need the write barrier. |
394 MemOperand StackOperand(Variable* var); | 374 MemOperand StackOperand(Variable* var); |
395 | 375 |
396 // An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT) | 376 // An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT) |
397 // variable. May emit code to traverse the context chain, loading the | 377 // variable. May emit code to traverse the context chain, loading the |
398 // found context into the scratch register. Writing to this operand will | 378 // found context into the scratch register. Writing to this operand will |
399 // need the write barrier if location is CONTEXT. | 379 // need the write barrier if location is CONTEXT. |
400 MemOperand VarOperand(Variable* var, Register scratch); | 380 MemOperand VarOperand(Variable* var, Register scratch); |
401 | 381 |
402 void VisitForEffect(Expression* expr) { | 382 void VisitForEffect(Expression* expr) { |
| 383 if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck(); |
403 EffectContext context(this); | 384 EffectContext context(this); |
404 Visit(expr); | 385 Visit(expr); |
405 PrepareForBailout(expr, NO_REGISTERS); | 386 PrepareForBailout(expr, NO_REGISTERS); |
406 } | 387 } |
407 | 388 |
408 void VisitForAccumulatorValue(Expression* expr) { | 389 void VisitForAccumulatorValue(Expression* expr) { |
| 390 if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck(); |
409 AccumulatorValueContext context(this); | 391 AccumulatorValueContext context(this); |
410 Visit(expr); | 392 Visit(expr); |
411 PrepareForBailout(expr, TOS_REG); | 393 PrepareForBailout(expr, TOS_REG); |
412 } | 394 } |
413 | 395 |
414 void VisitForStackValue(Expression* expr) { | 396 void VisitForStackValue(Expression* expr) { |
| 397 if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck(); |
415 StackValueContext context(this); | 398 StackValueContext context(this); |
416 Visit(expr); | 399 Visit(expr); |
417 PrepareForBailout(expr, NO_REGISTERS); | 400 PrepareForBailout(expr, NO_REGISTERS); |
418 } | 401 } |
419 | 402 |
420 void VisitForControl(Expression* expr, | 403 void VisitForControl(Expression* expr, |
421 Label* if_true, | 404 Label* if_true, |
422 Label* if_false, | 405 Label* if_false, |
423 Label* fall_through) { | 406 Label* fall_through) { |
| 407 if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck(); |
424 TestContext context(this, expr, if_true, if_false, fall_through); | 408 TestContext context(this, expr, if_true, if_false, fall_through); |
425 Visit(expr); | 409 Visit(expr); |
426 // For test contexts, we prepare for bailout before branching, not at | 410 // For test contexts, we prepare for bailout before branching, not at |
427 // the end of the entire expression. This happens as part of visiting | 411 // the end of the entire expression. This happens as part of visiting |
428 // the expression. | 412 // the expression. |
429 } | 413 } |
430 | 414 |
431 void VisitInDuplicateContext(Expression* expr); | 415 void VisitInDuplicateContext(Expression* expr); |
432 | 416 |
433 void VisitDeclarations(ZoneList<Declaration*>* declarations) override; | 417 void VisitDeclarations(ZoneList<Declaration*>* declarations) override; |
434 void DeclareModules(Handle<FixedArray> descriptions); | 418 void DeclareModules(Handle<FixedArray> descriptions); |
435 void DeclareGlobals(Handle<FixedArray> pairs); | 419 void DeclareGlobals(Handle<FixedArray> pairs); |
436 int DeclareGlobalsFlags(); | 420 int DeclareGlobalsFlags(); |
437 | 421 |
| 422 // Push, pop or drop values onto/from the operand stack. |
| 423 void PushOperand(Register reg); |
| 424 void PopOperand(Register reg); |
| 425 void DropOperands(int count); |
| 426 |
| 427 // Convenience helpers for pushing onto the operand stack. |
| 428 void PushOperand(MemOperand operand); |
| 429 void PushOperand(Handle<Object> handle); |
| 430 void PushOperand(Smi* smi); |
| 431 |
| 432 // Convenience helper for calling a runtime function that consumes arguments |
| 433 // from the operand stack (only usable for functions with known arity). |
| 434 void CallRuntimeWithOperands(Runtime::FunctionId function_id); |
| 435 |
| 436 // Static tracking of the operand stack depth. |
| 437 void OperandStackDepthDecrement(int count); |
| 438 void OperandStackDepthIncrement(int count); |
| 439 |
| 440 // Generate debug code that verifies that our static tracking of the operand |
| 441 // stack depth is in sync with the actual operand stack during runtime. |
| 442 void EmitOperandStackDepthCheck(); |
| 443 |
438 // Generate code to create an iterator result object. The "value" property is | 444 // Generate code to create an iterator result object. The "value" property is |
439 // set to a value popped from the stack, and "done" is set according to the | 445 // set to a value popped from the stack, and "done" is set according to the |
440 // argument. The result object is left in the result register. | 446 // argument. The result object is left in the result register. |
441 void EmitCreateIteratorResult(bool done); | 447 void EmitCreateIteratorResult(bool done); |
442 | 448 |
443 // Try to perform a comparison as a fast inlined literal compare if | 449 // Try to perform a comparison as a fast inlined literal compare if |
444 // the operands allow it. Returns true if the compare operations | 450 // the operands allow it. Returns true if the compare operations |
445 // has been matched and all code generated; false otherwise. | 451 // has been matched and all code generated; false otherwise. |
446 bool TryLiteralCompare(CompareOperation* compare); | 452 bool TryLiteralCompare(CompareOperation* compare); |
447 | 453 |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 | 987 |
982 MacroAssembler* masm_; | 988 MacroAssembler* masm_; |
983 CompilationInfo* info_; | 989 CompilationInfo* info_; |
984 Isolate* isolate_; | 990 Isolate* isolate_; |
985 Zone* zone_; | 991 Zone* zone_; |
986 Scope* scope_; | 992 Scope* scope_; |
987 Label return_label_; | 993 Label return_label_; |
988 NestedStatement* nesting_stack_; | 994 NestedStatement* nesting_stack_; |
989 int loop_depth_; | 995 int loop_depth_; |
990 int try_catch_depth_; | 996 int try_catch_depth_; |
| 997 int operand_stack_depth_; |
991 ZoneList<Handle<Object> >* globals_; | 998 ZoneList<Handle<Object> >* globals_; |
992 Handle<FixedArray> modules_; | 999 Handle<FixedArray> modules_; |
993 int module_index_; | 1000 int module_index_; |
994 const ExpressionContext* context_; | 1001 const ExpressionContext* context_; |
995 ZoneList<BailoutEntry> bailout_entries_; | 1002 ZoneList<BailoutEntry> bailout_entries_; |
996 ZoneList<BackEdgeEntry> back_edges_; | 1003 ZoneList<BackEdgeEntry> back_edges_; |
997 ZoneVector<HandlerTableEntry> handler_table_; | 1004 ZoneVector<HandlerTableEntry> handler_table_; |
998 int ic_total_count_; | 1005 int ic_total_count_; |
999 Handle<Cell> profiling_counter_; | 1006 Handle<Cell> profiling_counter_; |
1000 bool generate_debug_code_; | 1007 bool generate_debug_code_; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1086 Address start_; | 1093 Address start_; |
1087 Address instruction_start_; | 1094 Address instruction_start_; |
1088 uint32_t length_; | 1095 uint32_t length_; |
1089 }; | 1096 }; |
1090 | 1097 |
1091 | 1098 |
1092 } // namespace internal | 1099 } // namespace internal |
1093 } // namespace v8 | 1100 } // namespace v8 |
1094 | 1101 |
1095 #endif // V8_FULL_CODEGEN_FULL_CODEGEN_H_ | 1102 #endif // V8_FULL_CODEGEN_FULL_CODEGEN_H_ |
OLD | NEW |