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 helpers for pushing/popping multiple operands. |
| 433 void PushOperands(Register reg1, Register reg2); |
| 434 void PushOperands(Register reg1, Register reg2, Register reg3); |
| 435 void PushOperands(Register reg1, Register reg2, Register reg3, Register reg4); |
| 436 void PopOperands(Register reg1, Register reg2); |
| 437 |
| 438 // Convenience helper for calling a runtime function that consumes arguments |
| 439 // from the operand stack (only usable for functions with known arity). |
| 440 void CallRuntimeWithOperands(Runtime::FunctionId function_id); |
| 441 |
| 442 // Static tracking of the operand stack depth. |
| 443 void OperandStackDepthDecrement(int count); |
| 444 void OperandStackDepthIncrement(int count); |
| 445 |
| 446 // Generate debug code that verifies that our static tracking of the operand |
| 447 // stack depth is in sync with the actual operand stack during runtime. |
| 448 void EmitOperandStackDepthCheck(); |
| 449 |
438 // Generate code to create an iterator result object. The "value" property is | 450 // 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 | 451 // 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. | 452 // argument. The result object is left in the result register. |
441 void EmitCreateIteratorResult(bool done); | 453 void EmitCreateIteratorResult(bool done); |
442 | 454 |
443 // Try to perform a comparison as a fast inlined literal compare if | 455 // Try to perform a comparison as a fast inlined literal compare if |
444 // the operands allow it. Returns true if the compare operations | 456 // the operands allow it. Returns true if the compare operations |
445 // has been matched and all code generated; false otherwise. | 457 // has been matched and all code generated; false otherwise. |
446 bool TryLiteralCompare(CompareOperation* compare); | 458 bool TryLiteralCompare(CompareOperation* compare); |
447 | 459 |
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 | 992 |
981 MacroAssembler* masm_; | 993 MacroAssembler* masm_; |
982 CompilationInfo* info_; | 994 CompilationInfo* info_; |
983 Isolate* isolate_; | 995 Isolate* isolate_; |
984 Zone* zone_; | 996 Zone* zone_; |
985 Scope* scope_; | 997 Scope* scope_; |
986 Label return_label_; | 998 Label return_label_; |
987 NestedStatement* nesting_stack_; | 999 NestedStatement* nesting_stack_; |
988 int loop_depth_; | 1000 int loop_depth_; |
989 int try_catch_depth_; | 1001 int try_catch_depth_; |
| 1002 int operand_stack_depth_; |
990 ZoneList<Handle<Object> >* globals_; | 1003 ZoneList<Handle<Object> >* globals_; |
991 Handle<FixedArray> modules_; | 1004 Handle<FixedArray> modules_; |
992 int module_index_; | 1005 int module_index_; |
993 const ExpressionContext* context_; | 1006 const ExpressionContext* context_; |
994 ZoneList<BailoutEntry> bailout_entries_; | 1007 ZoneList<BailoutEntry> bailout_entries_; |
995 ZoneList<BackEdgeEntry> back_edges_; | 1008 ZoneList<BackEdgeEntry> back_edges_; |
996 ZoneVector<HandlerTableEntry> handler_table_; | 1009 ZoneVector<HandlerTableEntry> handler_table_; |
997 int ic_total_count_; | 1010 int ic_total_count_; |
998 Handle<Cell> profiling_counter_; | 1011 Handle<Cell> profiling_counter_; |
999 | 1012 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1084 Address start_; | 1097 Address start_; |
1085 Address instruction_start_; | 1098 Address instruction_start_; |
1086 uint32_t length_; | 1099 uint32_t length_; |
1087 }; | 1100 }; |
1088 | 1101 |
1089 | 1102 |
1090 } // namespace internal | 1103 } // namespace internal |
1091 } // namespace v8 | 1104 } // namespace v8 |
1092 | 1105 |
1093 #endif // V8_FULL_CODEGEN_FULL_CODEGEN_H_ | 1106 #endif // V8_FULL_CODEGEN_FULL_CODEGEN_H_ |
OLD | NEW |