V8 Project
full-codegen.h
Go to the documentation of this file.
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
3 // found in the LICENSE file.
4 
5 #ifndef V8_FULL_CODEGEN_H_
6 #define V8_FULL_CODEGEN_H_
7 
8 #include "src/v8.h"
9 
10 #include "src/allocation.h"
11 #include "src/assert-scope.h"
12 #include "src/ast.h"
13 #include "src/code-stubs.h"
14 #include "src/codegen.h"
15 #include "src/compiler.h"
16 #include "src/data-flow.h"
17 #include "src/globals.h"
18 #include "src/objects.h"
19 
20 namespace v8 {
21 namespace internal {
22 
23 // Forward declarations.
24 class JumpPatchSite;
25 
26 // AST node visitor which can tell whether a given statement will be breakable
27 // when the code is compiled by the full compiler in the debugger. This means
28 // that there will be an IC (load/store/call) in the code generated for the
29 // debugger to piggybag on.
31  public:
33  InitializeAstVisitor(zone);
34  }
35 
36  void Check(Statement* stmt);
37  void Check(Expression* stmt);
38 
39  bool is_breakable() { return is_breakable_; }
40 
41  private:
42  // AST node visit functions.
43 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
45 #undef DECLARE_VISIT
46 
48 
51 };
52 
53 
54 // -----------------------------------------------------------------------------
55 // Full code generator.
56 
58  public:
59  enum State {
61  TOS_REG
62  };
63 
65  : masm_(masm),
66  info_(info),
67  scope_(info->scope()),
69  loop_depth_(0),
70  globals_(NULL),
71  context_(NULL),
72  bailout_entries_(info->HasDeoptimizationSupport()
73  ? info->function()->ast_node_count() : 0,
74  info->zone()),
75  back_edges_(2, info->zone()),
76  ic_total_count_(0) {
77  DCHECK(!info->IsStub());
78  Initialize();
79  }
80 
81  void Initialize();
82 
83  static bool MakeCode(CompilationInfo* info);
84 
85  // Encode state and pc-offset as a BitField<type, start, size>.
86  // Only use 30 bits because we encode the result as a smi.
87  class StateField : public BitField<State, 0, 1> { };
88  class PcField : public BitField<unsigned, 1, 30-1> { };
89 
90  static const char* State2String(State state) {
91  switch (state) {
92  case NO_REGISTERS: return "NO_REGISTERS";
93  case TOS_REG: return "TOS_REG";
94  }
95  UNREACHABLE();
96  return NULL;
97  }
98 
99  static const int kMaxBackEdgeWeight = 127;
100 
101  // Platform-specific code size multiplier.
102 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
103  static const int kCodeSizeMultiplier = 105;
104  static const int kBootCodeSizeMultiplier = 100;
105 #elif V8_TARGET_ARCH_X64
106  static const int kCodeSizeMultiplier = 170;
107  static const int kBootCodeSizeMultiplier = 140;
108 #elif V8_TARGET_ARCH_ARM
109  static const int kCodeSizeMultiplier = 149;
110  static const int kBootCodeSizeMultiplier = 110;
111 #elif V8_TARGET_ARCH_ARM64
112 // TODO(all): Copied ARM value. Check this is sensible for ARM64.
113  static const int kCodeSizeMultiplier = 149;
114  static const int kBootCodeSizeMultiplier = 110;
115 #elif V8_TARGET_ARCH_MIPS
116  static const int kCodeSizeMultiplier = 149;
117  static const int kBootCodeSizeMultiplier = 120;
118 #elif V8_TARGET_ARCH_MIPS64
119  static const int kCodeSizeMultiplier = 149;
120  static const int kBootCodeSizeMultiplier = 120;
121 #else
122 #error Unsupported target architecture.
123 #endif
124 
125  private:
126  class Breakable;
127  class Iteration;
128 
129  class TestContext;
130 
132  public:
133  explicit NestedStatement(FullCodeGenerator* codegen) : codegen_(codegen) {
134  // Link into codegen's nesting stack.
135  previous_ = codegen->nesting_stack_;
136  codegen->nesting_stack_ = this;
137  }
138  virtual ~NestedStatement() {
139  // Unlink from codegen's nesting stack.
140  DCHECK_EQ(this, codegen_->nesting_stack_);
141  codegen_->nesting_stack_ = previous_;
142  }
143 
144  virtual Breakable* AsBreakable() { return NULL; }
145  virtual Iteration* AsIteration() { return NULL; }
146 
147  virtual bool IsContinueTarget(Statement* target) { return false; }
148  virtual bool IsBreakTarget(Statement* target) { return false; }
149 
150  // Notify the statement that we are exiting it via break, continue, or
151  // return and give it a chance to generate cleanup code. Return the
152  // next outer statement in the nesting stack. We accumulate in
153  // *stack_depth the amount to drop the stack and in *context_length the
154  // number of context chain links to unwind as we traverse the nesting
155  // stack from an exit to its target.
156  virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
157  return previous_;
158  }
159 
160  protected:
161  MacroAssembler* masm() { return codegen_->masm(); }
162 
165 
166  private:
168  };
169 
170  // A breakable statement such as a block.
171  class Breakable : public NestedStatement {
172  public:
174  : NestedStatement(codegen), statement_(statement) {
175  }
176  virtual ~Breakable() {}
177 
178  virtual Breakable* AsBreakable() { return this; }
179  virtual bool IsBreakTarget(Statement* target) {
180  return statement() == target;
181  }
182 
184  Label* break_label() { return &break_label_; }
185 
186  private:
189  };
190 
191  // An iteration statement such as a while, for, or do loop.
192  class Iteration : public Breakable {
193  public:
195  : Breakable(codegen, statement) {
196  }
197  virtual ~Iteration() {}
198 
199  virtual Iteration* AsIteration() { return this; }
200  virtual bool IsContinueTarget(Statement* target) {
201  return statement() == target;
202  }
203 
204  Label* continue_label() { return &continue_label_; }
205 
206  private:
208  };
209 
210  // A nested block statement.
211  class NestedBlock : public Breakable {
212  public:
213  NestedBlock(FullCodeGenerator* codegen, Block* block)
214  : Breakable(codegen, block) {
215  }
216  virtual ~NestedBlock() {}
217 
218  virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
219  if (statement()->AsBlock()->scope() != NULL) {
220  ++(*context_length);
221  }
222  return previous_;
223  }
224  };
225 
226  // The try block of a try/catch statement.
227  class TryCatch : public NestedStatement {
228  public:
229  explicit TryCatch(FullCodeGenerator* codegen) : NestedStatement(codegen) {
230  }
231  virtual ~TryCatch() {}
232 
233  virtual NestedStatement* Exit(int* stack_depth, int* context_length);
234  };
235 
236  // The try block of a try/finally statement.
237  class TryFinally : public NestedStatement {
238  public:
239  TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
240  : NestedStatement(codegen), finally_entry_(finally_entry) {
241  }
242  virtual ~TryFinally() {}
243 
244  virtual NestedStatement* Exit(int* stack_depth, int* context_length);
245 
246  private:
248  };
249 
250  // The finally block of a try/finally statement.
251  class Finally : public NestedStatement {
252  public:
253  static const int kElementCount = 5;
254 
255  explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { }
256  virtual ~Finally() {}
257 
258  virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
259  *stack_depth += kElementCount;
260  return previous_;
261  }
262  };
263 
264  // The body of a for/in loop.
265  class ForIn : public Iteration {
266  public:
267  static const int kElementCount = 5;
268 
269  ForIn(FullCodeGenerator* codegen, ForInStatement* statement)
270  : Iteration(codegen, statement) {
271  }
272  virtual ~ForIn() {}
273 
274  virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
275  *stack_depth += kElementCount;
276  return previous_;
277  }
278  };
279 
280 
281  // The body of a with or catch.
282  class WithOrCatch : public NestedStatement {
283  public:
284  explicit WithOrCatch(FullCodeGenerator* codegen)
285  : NestedStatement(codegen) {
286  }
287  virtual ~WithOrCatch() {}
288 
289  virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
290  ++(*context_length);
291  return previous_;
292  }
293  };
294 
295  // Type of a member function that generates inline code for a native function.
296  typedef void (FullCodeGenerator::*InlineFunctionGenerator)(CallRuntime* expr);
297 
299 
300  // A platform-specific utility to overwrite the accumulator register
301  // with a GC-safe value.
303 
304  // Determine whether or not to inline the smi case for the given
305  // operation.
307 
308  // Helper function to convert a pure value into a test context. The value
309  // is expected on the stack or the accumulator, depending on the platform.
310  // See the platform-specific implementation for details.
311  void DoTest(Expression* condition,
312  Label* if_true,
313  Label* if_false,
314  Label* fall_through);
315  void DoTest(const TestContext* context);
316 
317  // Helper function to split control flow and avoid a branch to the
318  // fall-through label if it is set up.
319 #if V8_TARGET_ARCH_MIPS
320  void Split(Condition cc,
321  Register lhs,
322  const Operand& rhs,
323  Label* if_true,
324  Label* if_false,
325  Label* fall_through);
326 #elif V8_TARGET_ARCH_MIPS64
327  void Split(Condition cc,
328  Register lhs,
329  const Operand& rhs,
330  Label* if_true,
331  Label* if_false,
332  Label* fall_through);
333 #else // All non-mips arch.
335  Label* if_true,
336  Label* if_false,
337  Label* fall_through);
338 #endif // V8_TARGET_ARCH_MIPS
339 
340  // Load the value of a known (PARAMETER, LOCAL, or CONTEXT) variable into
341  // a register. Emits a context chain walk if if necessary (so does
342  // SetVar) so avoid calling both on the same variable.
343  void GetVar(Register destination, Variable* var);
344 
345  // Assign to a known (PARAMETER, LOCAL, or CONTEXT) variable. If it's in
346  // the context, the write barrier will be emitted and source, scratch0,
347  // scratch1 will be clobbered. Emits a context chain walk if if necessary
348  // (so does GetVar) so avoid calling both on the same variable.
349  void SetVar(Variable* var,
350  Register source,
351  Register scratch0,
352  Register scratch1);
353 
354  // An operand used to read/write a stack-allocated (PARAMETER or LOCAL)
355  // variable. Writing does not need the write barrier.
357 
358  // An operand used to read/write a known (PARAMETER, LOCAL, or CONTEXT)
359  // variable. May emit code to traverse the context chain, loading the
360  // found context into the scratch register. Writing to this operand will
361  // need the write barrier if location is CONTEXT.
363 
365  EffectContext context(this);
366  Visit(expr);
368  }
369 
372  Visit(expr);
373  PrepareForBailout(expr, TOS_REG);
374  }
375 
378  Visit(expr);
380  }
381 
383  Label* if_true,
384  Label* if_false,
385  Label* fall_through) {
386  TestContext context(this, expr, if_true, if_false, fall_through);
387  Visit(expr);
388  // For test contexts, we prepare for bailout before branching, not at
389  // the end of the entire expression. This happens as part of visiting
390  // the expression.
391  }
392 
394 
395  void VisitDeclarations(ZoneList<Declaration*>* declarations);
396  void DeclareModules(Handle<FixedArray> descriptions);
398  int DeclareGlobalsFlags();
399 
400  // Generate code to allocate all (including nested) modules and contexts.
401  // Because of recursive linking and the presence of module alias declarations,
402  // this has to be a separate pass _before_ populating or executing any module.
403  void AllocateModules(ZoneList<Declaration*>* declarations);
404 
405  // Generate code to create an iterator result object. The "value" property is
406  // set to a value popped from the stack, and "done" is set according to the
407  // argument. The result object is left in the result register.
408  void EmitCreateIteratorResult(bool done);
409 
410  // Try to perform a comparison as a fast inlined literal compare if
411  // the operands allow it. Returns true if the compare operations
412  // has been matched and all code generated; false otherwise.
413  bool TryLiteralCompare(CompareOperation* compare);
414 
415  // Platform-specific code for comparing the type of a value with
416  // a given literal string.
418  Expression* sub_expr,
419  Handle<String> check);
420 
421  // Platform-specific code for equality comparison with a nil-like value.
422  void EmitLiteralCompareNil(CompareOperation* expr,
423  Expression* sub_expr,
424  NilValue nil);
425 
426  // Bailout support.
427  void PrepareForBailout(Expression* node, State state);
428  void PrepareForBailoutForId(BailoutId id, State state);
429 
430  // Feedback slot support. The feedback vector will be cleared during gc and
431  // collected by the type-feedback oracle.
433  return info_->feedback_vector();
434  }
435  void EnsureSlotContainsAllocationSite(int slot);
436 
437  // Record a call's return site offset, used to rebuild the frame if the
438  // called function was inlined at the site.
439  void RecordJSReturnSite(Call* call);
440 
441  // Prepare for bailout before a test (or compare) and branch. If
442  // should_normalize, then the following comparison will not handle the
443  // canonical JS true value so we will insert a (dead) test against true at
444  // the actual bailout target from the optimized code. If not
445  // should_normalize, the true and false labels are ignored.
447  bool should_normalize,
448  Label* if_true,
449  Label* if_false);
450 
451  // If enabled, emit debug code for checking that the current context is
452  // neither a with nor a catch context.
454 
455  // This is meant to be called at loop back edges, |back_edge_target| is
456  // the jump target of the back edge and is used to approximate the amount
457  // of code inside the loop.
459  Label* back_edge_target);
460  // Record the OSR AST id corresponding to a back edge in the code.
461  void RecordBackEdge(BailoutId osr_ast_id);
462  // Emit a table of back edge ids, pcs and loop depths into the code stream.
463  // Return the offset of the start of the table.
464  unsigned EmitBackEdgeTable();
465 
468 
469  // Emit code to pop values from the stack associated with nested statements
470  // like try/catch, try/finally, etc, running the finallies and unwinding the
471  // handlers as needed.
472  void EmitUnwindBeforeReturn();
473 
474  // Platform-specific return sequence
476 
477  // Platform-specific code sequences for calls
478  void EmitCall(Call* expr, CallICState::CallType = CallICState::FUNCTION);
479  void EmitCallWithLoadIC(Call* expr);
480  void EmitSuperCallWithLoadIC(Call* expr);
481  void EmitKeyedCallWithLoadIC(Call* expr, Expression* key);
482 
483  // Platform-specific code for inline runtime calls.
485 
486  void EmitInlineRuntimeCall(CallRuntime* expr);
487 
488 #define EMIT_INLINE_RUNTIME_CALL(name, x, y) \
489  void Emit##name(CallRuntime* expr);
491 #undef EMIT_INLINE_RUNTIME_CALL
492 
493  // Platform-specific code for resuming generators.
495  Expression *value,
496  JSGeneratorObject::ResumeMode resume_mode);
497 
498  // Platform-specific code for loading variables.
499  void EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
500  TypeofState typeof_state,
501  Label* slow);
503  void EmitDynamicLookupFastCase(VariableProxy* proxy,
504  TypeofState typeof_state,
505  Label* slow,
506  Label* done);
507  void EmitVariableLoad(VariableProxy* proxy);
508 
509  void EmitAccessor(Expression* expression);
510 
511  // Expects the arguments and the function already pushed.
512  void EmitResolvePossiblyDirectEval(int arg_count);
513 
514  // Platform-specific support for allocating a new closure based on
515  // the given function info.
516  void EmitNewClosure(Handle<SharedFunctionInfo> info, bool pretenure);
517 
518  // Platform-specific support for compiling assignments.
519 
520  // Load a value from a named property.
521  // The receiver is left on the stack by the IC.
522  void EmitNamedPropertyLoad(Property* expr);
523 
524  // Load a value from super.named prroperty.
525  // Expect receiver ('this' value) and home_object on the stack.
526  void EmitNamedSuperPropertyLoad(Property* expr);
527 
528  // Load a value from a keyed property.
529  // The receiver and the key is left on the stack by the IC.
530  void EmitKeyedPropertyLoad(Property* expr);
531 
532  // Apply the compound assignment operator. Expects the left operand on top
533  // of the stack and the right one in the accumulator.
534  void EmitBinaryOp(BinaryOperation* expr,
535  Token::Value op,
537 
538  // Helper functions for generating inlined smi code for certain
539  // binary operations.
540  void EmitInlineSmiBinaryOp(BinaryOperation* expr,
541  Token::Value op,
543  Expression* left,
544  Expression* right);
545 
546  // Assign to the given expression as if via '='. The right-hand-side value
547  // is expected in the accumulator.
549 
550  // Complete a variable assignment. The right-hand-side value is expected
551  // in the accumulator.
553  Token::Value op);
554 
555  // Helper functions to EmitVariableAssignment
557  MemOperand location);
558 
559  // Complete a named property assignment. The receiver is expected on top
560  // of the stack and the right-hand-side value in the accumulator.
561  void EmitNamedPropertyAssignment(Assignment* expr);
562 
563  // Complete a super named property assignment. The right-hand-side value
564  // is expected in accumulator.
565  void EmitNamedSuperPropertyAssignment(Assignment* expr);
566 
567  // Complete a keyed property assignment. The receiver and key are
568  // expected on top of the stack and the right-hand-side value in the
569  // accumulator.
570  void EmitKeyedPropertyAssignment(Assignment* expr);
571 
572  void EmitLoadHomeObject(SuperReference* expr);
573 
574  void CallIC(Handle<Code> code,
576 
580 
581  void SetFunctionPosition(FunctionLiteral* fun);
582  void SetReturnPosition(FunctionLiteral* fun);
583  void SetStatementPosition(Statement* stmt);
584  void SetExpressionPosition(Expression* expr);
585  void SetSourcePosition(int pos);
586 
587  // Non-local control flow support.
590 
591  // Loop nesting counter.
592  int loop_depth() { return loop_depth_; }
595  DCHECK(loop_depth_ > 0);
596  loop_depth_--;
597  }
598 
599  MacroAssembler* masm() { return masm_; }
600 
601  class ExpressionContext;
602  const ExpressionContext* context() { return context_; }
604 
606  bool is_eval() { return info_->is_eval(); }
607  bool is_native() { return info_->is_native(); }
608  StrictMode strict_mode() { return function()->strict_mode(); }
609  FunctionLiteral* function() { return info_->function(); }
610  Scope* scope() { return scope_; }
611 
614 
615  // Set fields in the stack frame. Offsets are the frame pointer relative
616  // offsets defined in, e.g., StandardFrameConstants.
617  void StoreToFrameField(int frame_offset, Register value);
618 
619  // Load a value from the current context. Indices are defined as an enum
620  // in v8::internal::Context.
621  void LoadContextField(Register dst, int context_index);
622 
623  // Push the function argument for the runtime functions PushWithContext
624  // and PushCatchContext.
626 
627  // AST node visit functions.
628 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
630 #undef DECLARE_VISIT
631 
632  void VisitComma(BinaryOperation* expr);
633  void VisitLogicalExpression(BinaryOperation* expr);
634  void VisitArithmeticExpression(BinaryOperation* expr);
635 
637 
638  void Generate();
641 
643 
644  struct BailoutEntry {
646  unsigned pc_and_state;
647  };
648 
649  struct BackEdgeEntry {
651  unsigned pc;
653  };
654 
656  public:
658  : masm_(codegen->masm()), old_(codegen->context()), codegen_(codegen) {
659  codegen->set_new_context(this);
660  }
661 
662  virtual ~ExpressionContext() {
663  codegen_->set_new_context(old_);
664  }
665 
666  Isolate* isolate() const { return codegen_->isolate(); }
667 
668  // Convert constant control flow (true or false) to the result expected for
669  // this expression context.
670  virtual void Plug(bool flag) const = 0;
671 
672  // Emit code to convert a pure value (in a register, known variable
673  // location, as a literal, or on top of the stack) into the result
674  // expected according to this expression context.
675  virtual void Plug(Register reg) const = 0;
676  virtual void Plug(Variable* var) const = 0;
677  virtual void Plug(Handle<Object> lit) const = 0;
678  virtual void Plug(Heap::RootListIndex index) const = 0;
679  virtual void PlugTOS() const = 0;
680 
681  // Emit code to convert pure control flow to a pair of unbound labels into
682  // the result expected according to this expression context. The
683  // implementation will bind both labels unless it's a TestContext, which
684  // won't bind them at this point.
685  virtual void Plug(Label* materialize_true,
686  Label* materialize_false) const = 0;
687 
688  // Emit code to discard count elements from the top of stack, then convert
689  // a pure value into the result expected according to this expression
690  // context.
691  virtual void DropAndPlug(int count, Register reg) const = 0;
692 
693  // Set up branch labels for a test expression. The three Label** parameters
694  // are output parameters.
695  virtual void PrepareTest(Label* materialize_true,
696  Label* materialize_false,
697  Label** if_true,
698  Label** if_false,
699  Label** fall_through) const = 0;
700 
701  // Returns true if we are evaluating only for side effects (i.e. if the
702  // result will be discarded).
703  virtual bool IsEffect() const { return false; }
704 
705  // Returns true if we are evaluating for the value (in accu/on stack).
706  virtual bool IsAccumulatorValue() const { return false; }
707  virtual bool IsStackValue() const { return false; }
708 
709  // Returns true if we are branching on the value rather than materializing
710  // it. Only used for asserts.
711  virtual bool IsTest() const { return false; }
712 
713  protected:
714  FullCodeGenerator* codegen() const { return codegen_; }
715  MacroAssembler* masm() const { return masm_; }
717 
718  private:
720  FullCodeGenerator* codegen_;
721  };
722 
724  public:
726  : ExpressionContext(codegen) { }
727 
728  virtual void Plug(bool flag) const;
729  virtual void Plug(Register reg) const;
730  virtual void Plug(Label* materialize_true, Label* materialize_false) const;
731  virtual void Plug(Variable* var) const;
732  virtual void Plug(Handle<Object> lit) const;
733  virtual void Plug(Heap::RootListIndex) const;
734  virtual void PlugTOS() const;
735  virtual void DropAndPlug(int count, Register reg) const;
736  virtual void PrepareTest(Label* materialize_true,
737  Label* materialize_false,
738  Label** if_true,
739  Label** if_false,
740  Label** fall_through) const;
741  virtual bool IsAccumulatorValue() const { return true; }
742  };
743 
745  public:
747  : ExpressionContext(codegen) { }
748 
749  virtual void Plug(bool flag) const;
750  virtual void Plug(Register reg) const;
751  virtual void Plug(Label* materialize_true, Label* materialize_false) const;
752  virtual void Plug(Variable* var) const;
753  virtual void Plug(Handle<Object> lit) const;
754  virtual void Plug(Heap::RootListIndex) const;
755  virtual void PlugTOS() const;
756  virtual void DropAndPlug(int count, Register reg) const;
757  virtual void PrepareTest(Label* materialize_true,
758  Label* materialize_false,
759  Label** if_true,
760  Label** if_false,
761  Label** fall_through) const;
762  virtual bool IsStackValue() const { return true; }
763  };
764 
766  public:
769  Label* true_label,
770  Label* false_label,
771  Label* fall_through)
772  : ExpressionContext(codegen),
777 
778  static const TestContext* cast(const ExpressionContext* context) {
779  DCHECK(context->IsTest());
780  return reinterpret_cast<const TestContext*>(context);
781  }
782 
783  Expression* condition() const { return condition_; }
784  Label* true_label() const { return true_label_; }
785  Label* false_label() const { return false_label_; }
786  Label* fall_through() const { return fall_through_; }
787 
788  virtual void Plug(bool flag) const;
789  virtual void Plug(Register reg) const;
790  virtual void Plug(Label* materialize_true, Label* materialize_false) const;
791  virtual void Plug(Variable* var) const;
792  virtual void Plug(Handle<Object> lit) const;
793  virtual void Plug(Heap::RootListIndex) const;
794  virtual void PlugTOS() const;
795  virtual void DropAndPlug(int count, Register reg) const;
796  virtual void PrepareTest(Label* materialize_true,
797  Label* materialize_false,
798  Label** if_true,
799  Label** if_false,
800  Label** fall_through) const;
801  virtual bool IsTest() const { return true; }
802 
803  private:
805  Label* true_label_;
806  Label* false_label_;
808  };
809 
811  public:
812  explicit EffectContext(FullCodeGenerator* codegen)
813  : ExpressionContext(codegen) { }
814 
815  virtual void Plug(bool flag) const;
816  virtual void Plug(Register reg) const;
817  virtual void Plug(Label* materialize_true, Label* materialize_false) const;
818  virtual void Plug(Variable* var) const;
819  virtual void Plug(Handle<Object> lit) const;
820  virtual void Plug(Heap::RootListIndex) const;
821  virtual void PlugTOS() const;
822  virtual void DropAndPlug(int count, Register reg) const;
823  virtual void PrepareTest(Label* materialize_true,
824  Label* materialize_false,
825  Label** if_true,
826  Label** if_false,
827  Label** fall_through) const;
828  virtual bool IsEffect() const { return true; }
829  };
830 
847 
848  friend class NestedStatement;
849 
852 };
853 
854 
855 // A map from property names to getter/setter pairs allocated in the zone.
856 class AccessorTable: public TemplateHashMap<Literal,
857  ObjectLiteral::Accessors,
858  ZoneAllocationPolicy> {
859  public:
860  explicit AccessorTable(Zone* zone) :
861  TemplateHashMap<Literal, ObjectLiteral::Accessors,
862  ZoneAllocationPolicy>(Literal::Match,
863  ZoneAllocationPolicy(zone)),
864  zone_(zone) { }
865 
866  Iterator lookup(Literal* literal) {
867  Iterator it = find(literal, true, ZoneAllocationPolicy(zone_));
868  if (it->second == NULL) it->second = new(zone_) ObjectLiteral::Accessors();
869  return it;
870  }
871 
872  private:
874 };
875 
876 
878  public:
880  DCHECK(code->kind() == Code::FUNCTION);
882  Address table_address = instruction_start_ + code->back_edge_table_offset();
883  length_ = Memory::uint32_at(table_address);
884  start_ = table_address + kTableLengthSize;
885  }
886 
887  uint32_t length() { return length_; }
888 
890  return BailoutId(static_cast<int>(
892  }
893 
896  }
897 
899  return Memory::uint32_at(entry_at(index) + kPcOffsetOffset);
900  }
901 
902  Address pc(uint32_t index) {
903  return instruction_start_ + pc_offset(index);
904  }
905 
910  };
911 
912  // Increase allowed loop nesting level by one and patch those matching loops.
913  static void Patch(Isolate* isolate, Code* unoptimized_code);
914 
915  // Patch the back edge to the target state, provided the correct callee.
916  static void PatchAt(Code* unoptimized_code,
917  Address pc,
918  BackEdgeState target_state,
919  Code* replacement_code);
920 
921  // Change all patched back edges back to normal interrupts.
922  static void Revert(Isolate* isolate,
923  Code* unoptimized_code);
924 
925  // Change a back edge patched for on-stack replacement to perform a
926  // stack check first.
927  static void AddStackCheck(Handle<Code> code, uint32_t pc_offset);
928 
929  // Revert the patch by AddStackCheck.
930  static void RemoveStackCheck(Handle<Code> code, uint32_t pc_offset);
931 
932  // Return the current patch state of the back edge.
934  Code* unoptimized_code,
935  Address pc_after);
936 
937 #ifdef DEBUG
938  // Verify that all back edges of a certain loop depth are patched.
939  static bool Verify(Isolate* isolate, Code* unoptimized_code);
940 #endif // DEBUG
941 
942  private:
944  DCHECK(index < length_);
945  return start_ + index * kEntrySize;
946  }
947 
948  static const int kTableLengthSize = kIntSize;
949  static const int kAstIdOffset = 0 * kIntSize;
950  static const int kPcOffsetOffset = 1 * kIntSize;
951  static const int kLoopDepthOffset = 2 * kIntSize;
952  static const int kEntrySize = 3 * kIntSize;
953 
957 };
958 
959 
960 } } // namespace v8::internal
961 
962 #endif // V8_FULL_CODEGEN_H_
#define AST_NODE_LIST(V)
Definition: ast.h:102
Iterator lookup(Literal *literal)
Definition: full-codegen.h:866
static const int kLoopDepthOffset
Definition: full-codegen.h:951
static const int kTableLengthSize
Definition: full-codegen.h:948
uint32_t pc_offset(uint32_t index)
Definition: full-codegen.h:898
static const int kEntrySize
Definition: full-codegen.h:952
static void RemoveStackCheck(Handle< Code > code, uint32_t pc_offset)
uint32_t loop_depth(uint32_t index)
Definition: full-codegen.h:894
static void PatchAt(Code *unoptimized_code, Address pc, BackEdgeState target_state, Code *replacement_code)
BackEdgeTable(Code *code, DisallowHeapAllocation *required)
Definition: full-codegen.h:879
static void Patch(Isolate *isolate, Code *unoptimized_code)
Address entry_at(uint32_t index)
Definition: full-codegen.h:943
static void Revert(Isolate *isolate, Code *unoptimized_code)
static const int kAstIdOffset
Definition: full-codegen.h:949
static const int kPcOffsetOffset
Definition: full-codegen.h:950
BailoutId ast_id(uint32_t index)
Definition: full-codegen.h:889
static BackEdgeState GetBackEdgeState(Isolate *isolate, Code *unoptimized_code, Address pc_after)
static void AddStackCheck(Handle< Code > code, uint32_t pc_offset)
Address pc(uint32_t index)
Definition: full-codegen.h:902
DISALLOW_COPY_AND_ASSIGN(BreakableStatementChecker)
byte * instruction_start()
Definition: objects-inl.h:6176
unsigned back_edge_table_offset()
Definition: objects-inl.h:4834
Handle< Script > script() const
Definition: compiler.h:113
FunctionLiteral * function() const
Definition: compiler.h:107
Handle< TypeFeedbackVector > feedback_vector() const
Definition: compiler.h:239
virtual void Plug(Label *materialize_true, Label *materialize_false) const
virtual void DropAndPlug(int count, Register reg) const
virtual void PrepareTest(Label *materialize_true, Label *materialize_false, Label **if_true, Label **if_false, Label **fall_through) const
virtual void Plug(Heap::RootListIndex) const
virtual void Plug(Handle< Object > lit) const
virtual void Plug(Heap::RootListIndex index) const =0
NestedStatement(FullCodeGenerator *codegen)
Definition: full-codegen.h:133
virtual void Plug(Handle< Object > lit) const =0
virtual bool IsContinueTarget(Statement *target)
Definition: full-codegen.h:147
virtual bool IsBreakTarget(Statement *target)
Definition: full-codegen.h:148
virtual void PrepareTest(Label *materialize_true, Label *materialize_false, Label **if_true, Label **if_false, Label **fall_through) const =0
virtual void Plug(bool flag) const =0
ExpressionContext(FullCodeGenerator *codegen)
Definition: full-codegen.h:657
virtual NestedStatement * Exit(int *stack_depth, int *context_length)
Definition: full-codegen.h:156
virtual void Plug(Variable *var) const =0
virtual void Plug(Label *materialize_true, Label *materialize_false) const =0
virtual void Plug(Register reg) const =0
virtual void DropAndPlug(int count, Register reg) const =0
virtual bool IsBreakTarget(Statement *target)
Definition: full-codegen.h:179
Breakable(FullCodeGenerator *codegen, BreakableStatement *statement)
Definition: full-codegen.h:173
virtual void Plug(Variable *var) const
virtual void Plug(Heap::RootListIndex) const
virtual void PrepareTest(Label *materialize_true, Label *materialize_false, Label **if_true, Label **if_false, Label **fall_through) const
virtual void DropAndPlug(int count, Register reg) const
EffectContext(FullCodeGenerator *codegen)
Definition: full-codegen.h:812
virtual void Plug(Handle< Object > lit) const
virtual void Plug(Label *materialize_true, Label *materialize_false) const
virtual NestedStatement * Exit(int *stack_depth, int *context_length)
Definition: full-codegen.h:258
Finally(FullCodeGenerator *codegen)
Definition: full-codegen.h:255
ForIn(FullCodeGenerator *codegen, ForInStatement *statement)
Definition: full-codegen.h:269
virtual NestedStatement * Exit(int *stack_depth, int *context_length)
Definition: full-codegen.h:274
virtual bool IsContinueTarget(Statement *target)
Definition: full-codegen.h:200
Iteration(FullCodeGenerator *codegen, IterationStatement *statement)
Definition: full-codegen.h:194
virtual NestedStatement * Exit(int *stack_depth, int *context_length)
Definition: full-codegen.h:218
NestedBlock(FullCodeGenerator *codegen, Block *block)
Definition: full-codegen.h:213
virtual void Plug(Heap::RootListIndex) const
virtual void Plug(Handle< Object > lit) const
virtual void Plug(Variable *var) const
virtual void PrepareTest(Label *materialize_true, Label *materialize_false, Label **if_true, Label **if_false, Label **fall_through) const
virtual void DropAndPlug(int count, Register reg) const
virtual void Plug(Label *materialize_true, Label *materialize_false) const
virtual void Plug(Handle< Object > lit) const
virtual void Plug(Label *materialize_true, Label *materialize_false) const
virtual void PrepareTest(Label *materialize_true, Label *materialize_false, Label **if_true, Label **if_false, Label **fall_through) const
virtual void DropAndPlug(int count, Register reg) const
static const TestContext * cast(const ExpressionContext *context)
Definition: full-codegen.h:778
virtual void Plug(bool flag) const
virtual void Plug(Heap::RootListIndex) const
virtual void Plug(Variable *var) const
TestContext(FullCodeGenerator *codegen, Expression *condition, Label *true_label, Label *false_label, Label *fall_through)
Definition: full-codegen.h:767
virtual NestedStatement * Exit(int *stack_depth, int *context_length)
TryCatch(FullCodeGenerator *codegen)
Definition: full-codegen.h:229
virtual NestedStatement * Exit(int *stack_depth, int *context_length)
TryFinally(FullCodeGenerator *codegen, Label *finally_entry)
Definition: full-codegen.h:239
virtual NestedStatement * Exit(int *stack_depth, int *context_length)
Definition: full-codegen.h:289
WithOrCatch(FullCodeGenerator *codegen)
Definition: full-codegen.h:284
static const int kMaxBackEdgeWeight
Definition: full-codegen.h:99
void(FullCodeGenerator::* InlineFunctionGenerator)(CallRuntime *expr)
Definition: full-codegen.h:296
ZoneList< BailoutEntry > bailout_entries_
Definition: full-codegen.h:841
void VisitArithmeticExpression(BinaryOperation *expr)
void EmitAccessor(Expression *expression)
void Split(Condition cc, Label *if_true, Label *if_false, Label *fall_through)
void EmitBinaryOp(BinaryOperation *expr, Token::Value op, OverwriteMode mode)
void EmitLiteralCompareTypeof(Expression *expr, Expression *sub_expr, Handle< String > check)
void VisitDeclarations(ZoneList< Declaration * > *declarations)
void PrepareForBailoutForId(BailoutId id, State state)
void EmitNewClosure(Handle< SharedFunctionInfo > info, bool pretenure)
void GetVar(Register destination, Variable *var)
const ExpressionContext * context_
Definition: full-codegen.h:840
static Register context_register()
ZoneList< Handle< Object > > * globals_
Definition: full-codegen.h:837
void VisitForControl(Expression *expr, Label *if_true, Label *if_false, Label *fall_through)
Definition: full-codegen.h:382
void CallLoadIC(ContextualMode mode, TypeFeedbackId id=TypeFeedbackId::None())
void RecordBackEdge(BailoutId osr_ast_id)
void VisitLogicalExpression(BinaryOperation *expr)
MemOperand StackOperand(Variable *var)
void EmitVariableLoad(VariableProxy *proxy)
static bool MakeCode(CompilationInfo *info)
void SetVar(Variable *var, Register source, Register scratch0, Register scratch1)
MemOperand ContextSlotOperandCheckExtensions(Variable *var, Label *slow)
void EmitKeyedPropertyAssignment(Assignment *expr)
void DeclareGlobals(Handle< FixedArray > pairs)
void EmitResolvePossiblyDirectEval(int arg_count)
void VisitForStackValue(Expression *expr)
Definition: full-codegen.h:376
void EmitKeyedCallWithLoadIC(Call *expr, Expression *key)
void EmitKeyedPropertyLoad(Property *expr)
void AllocateModules(ZoneList< Declaration * > *declarations)
void PopulateDeoptimizationData(Handle< Code > code)
DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator)
void EmitDebugCheckDeclarationContext(Variable *variable)
NestedStatement * nesting_stack_
Definition: full-codegen.h:835
FunctionLiteral * function()
Definition: full-codegen.h:609
void EmitNamedSuperPropertyLoad(Property *expr)
bool TryLiteralCompare(CompareOperation *compare)
void SetStatementPosition(Statement *stmt)
Handle< FixedArray > FeedbackVector()
Definition: full-codegen.h:432
void StoreToFrameField(int frame_offset, Register value)
void LoadContextField(Register dst, int context_index)
void set_new_context(const ExpressionContext *context)
Definition: full-codegen.h:603
const ExpressionContext * context()
Definition: full-codegen.h:602
void EmitNamedPropertyLoad(Property *expr)
void EmitBackEdgeBookkeeping(IterationStatement *stmt, Label *back_edge_target)
void DoTest(Expression *condition, Label *if_true, Label *if_false, Label *fall_through)
void PopulateTypeFeedbackInfo(Handle< Code > code)
void VisitForAccumulatorValue(Expression *expr)
Definition: full-codegen.h:370
void PrepareForBailout(Expression *node, State state)
void CallStoreIC(TypeFeedbackId id=TypeFeedbackId::None())
MemOperand VarOperand(Variable *var, Register scratch)
void DeclareModules(Handle< FixedArray > descriptions)
void EmitGeneratorResume(Expression *generator, Expression *value, JSGeneratorObject::ResumeMode resume_mode)
void VisitForEffect(Expression *expr)
Definition: full-codegen.h:364
void EmitAssignment(Expression *expr)
void EmitCall(Call *expr, CallICState::CallType=CallICState::FUNCTION)
void SetFunctionPosition(FunctionLiteral *fun)
void EmitLoadHomeObject(SuperReference *expr)
void VisitComma(BinaryOperation *expr)
void EmitStoreToStackLocalOrContextSlot(Variable *var, MemOperand location)
static const char * State2String(State state)
Definition: full-codegen.h:90
void SetExpressionPosition(Expression *expr)
void EmitInlineSmiBinaryOp(BinaryOperation *expr, Token::Value op, OverwriteMode mode, Expression *left, Expression *right)
void EmitLiteralCompareNil(CompareOperation *expr, Expression *sub_expr, NilValue nil)
void EmitVariableAssignment(Variable *var, Token::Value op)
void CallIC(Handle< Code > code, TypeFeedbackId id=TypeFeedbackId::None())
void EmitCreateIteratorResult(bool done)
ZoneList< BackEdgeEntry > back_edges_
Definition: full-codegen.h:842
void EmitLoadGlobalCheckExtensions(VariableProxy *proxy, TypeofState typeof_state, Label *slow)
void EmitCallWithLoadIC(Call *expr)
void EnsureSlotContainsAllocationSite(int slot)
void PrepareForBailoutBeforeSplit(Expression *expr, bool should_normalize, Label *if_true, Label *if_false)
Handle< FixedArray > modules_
Definition: full-codegen.h:838
void EmitInlineRuntimeCall(CallRuntime *expr)
FullCodeGenerator(MacroAssembler *masm, CompilationInfo *info)
Definition: full-codegen.h:64
void EmitSuperCallWithLoadIC(Call *expr)
void EmitNamedSuperPropertyAssignment(Assignment *expr)
InlineFunctionGenerator FindInlineFunctionGenerator(Runtime::FunctionId id)
void EmitNamedPropertyAssignment(Assignment *expr)
Handle< FixedArray > handler_table_
Definition: full-codegen.h:844
static const InlineFunctionGenerator kInlineFunctionGenerators[]
Definition: full-codegen.h:298
void RecordJSReturnSite(Call *call)
static Register result_register()
void VisitForTypeofValue(Expression *expr)
void EmitDynamicLookupFastCase(VariableProxy *proxy, TypeofState typeof_state, Label *slow, Label *done)
bool ShouldInlineSmiCase(Token::Value op)
Handle< FixedArray > handler_table()
Definition: full-codegen.h:642
void SetReturnPosition(FunctionLiteral *fun)
void EmitProfilingCounterDecrement(int delta)
void VisitInDuplicateContext(Expression *expr)
static uint32_t & uint32_at(Address addr)
Definition: v8memory.h:24
Iterator find(Literal *key, bool insert=false, ZoneAllocationPolicy allocator=ZoneAllocationPolicy())
Definition: hashmap.h:339
static TypeFeedbackId None()
Definition: utils.h:945
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction pairs(ARM only)") DEFINE_BOOL(enable_unaligned_accesses
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define EMIT_INLINE_RUNTIME_CALL(name, x, y)
Definition: full-codegen.h:488
#define DECLARE_VISIT(type)
Definition: full-codegen.h:628
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
byte * Address
Definition: globals.h:101
NilValue
Definition: v8.h:97
const int kIntSize
Definition: globals.h:124
kFeedbackVectorOffset flag
Definition: objects-inl.h:5418
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
#define INLINE_FUNCTION_LIST(F)
Definition: runtime.h:659