1// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28
29#ifndef V8_MIPS_CODEGEN_MIPS_H_
30#define V8_MIPS_CODEGEN_MIPS_H_
31
32namespace v8 {
33namespace internal {
34
35// Forward declarations
36class CompilationInfo;
37class DeferredCode;
38class RegisterAllocator;
39class RegisterFile;
40
41enum InitState { CONST_INIT, NOT_CONST_INIT };
42enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
43
44
45// -------------------------------------------------------------------------
46// Code generation state
47
48// The state is passed down the AST by the code generator (and back up, in
49// the form of the state of the label pair).  It is threaded through the
50// call stack.  Constructing a state implicitly pushes it on the owning code
51// generator's stack of states, and destroying one implicitly pops it.
52
53class CodeGenState BASE_EMBEDDED {
54 public:
55  // Create an initial code generator state.  Destroying the initial state
56  // leaves the code generator with a NULL state.
57  explicit CodeGenState(CodeGenerator* owner);
58
59  // Create a code generator state based on a code generator's current
60  // state.  The new state has its own typeof state and pair of branch
61  // labels.
62  CodeGenState(CodeGenerator* owner,
63               JumpTarget* true_target,
64               JumpTarget* false_target);
65
66  // Destroy a code generator state and restore the owning code generator's
67  // previous state.
68  ~CodeGenState();
69
70  TypeofState typeof_state() const { return typeof_state_; }
71  JumpTarget* true_target() const { return true_target_; }
72  JumpTarget* false_target() const { return false_target_; }
73
74 private:
75  // The owning code generator.
76  CodeGenerator* owner_;
77
78  // A flag indicating whether we are compiling the immediate subexpression
79  // of a typeof expression.
80  TypeofState typeof_state_;
81
82  JumpTarget* true_target_;
83  JumpTarget* false_target_;
84
85  // The previous state of the owning code generator, restored when
86  // this state is destroyed.
87  CodeGenState* previous_;
88};
89
90
91
92// -------------------------------------------------------------------------
93// CodeGenerator
94
95class CodeGenerator: public AstVisitor {
96 public:
97  // Compilation mode.  Either the compiler is used as the primary
98  // compiler and needs to setup everything or the compiler is used as
99  // the secondary compiler for split compilation and has to handle
100  // bailouts.
101  enum Mode {
102    PRIMARY,
103    SECONDARY
104  };
105
106  // Takes a function literal, generates code for it. This function should only
107  // be called by compiler.cc.
108  static Handle<Code> MakeCode(CompilationInfo* info);
109
110  // Printing of AST, etc. as requested by flags.
111  static void MakeCodePrologue(CompilationInfo* info);
112
113  // Allocate and install the code.
114  static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
115                                       Code::Flags flags,
116                                       CompilationInfo* info);
117
118#ifdef ENABLE_LOGGING_AND_PROFILING
119  static bool ShouldGenerateLog(Expression* type);
120#endif
121
122  static void SetFunctionInfo(Handle<JSFunction> fun,
123                              FunctionLiteral* lit,
124                              bool is_toplevel,
125                              Handle<Script> script);
126
127  static void RecordPositions(MacroAssembler* masm, int pos);
128
129  // Accessors
130  MacroAssembler* masm() { return masm_; }
131  VirtualFrame* frame() const { return frame_; }
132  inline Handle<Script> script();
133
134  bool has_valid_frame() const { return frame_ != NULL; }
135
136  // Set the virtual frame to be new_frame, with non-frame register
137  // reference counts given by non_frame_registers.  The non-frame
138  // register reference counts of the old frame are returned in
139  // non_frame_registers.
140  void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
141
142  void DeleteFrame();
143
144  RegisterAllocator* allocator() const { return allocator_; }
145
146  CodeGenState* state() { return state_; }
147  void set_state(CodeGenState* state) { state_ = state; }
148
149  void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
150
151  static const int kUnknownIntValue = -1;
152
153  // Number of instructions used for the JS return sequence. The constant is
154  // used by the debugger to patch the JS return sequence.
155  static const int kJSReturnSequenceLength = 6;
156
157 private:
158  // Construction/Destruction.
159  explicit CodeGenerator(MacroAssembler* masm);
160  virtual ~CodeGenerator() { delete masm_; }
161
162  // Accessors.
163  inline bool is_eval();
164  Scope* scope() const { return scope_; }
165
166  // Generating deferred code.
167  void ProcessDeferred();
168
169  // State
170  bool has_cc() const  { return cc_reg_ != cc_always; }
171  TypeofState typeof_state() const { return state_->typeof_state(); }
172  JumpTarget* true_target() const  { return state_->true_target(); }
173  JumpTarget* false_target() const  { return state_->false_target(); }
174
175  // We don't track loop nesting level on mips yet.
176  int loop_nesting() const { return 0; }
177
178  // Node visitors.
179  void VisitStatements(ZoneList<Statement*>* statements);
180
181#define DEF_VISIT(type) \
182  void Visit##type(type* node);
183  AST_NODE_LIST(DEF_VISIT)
184#undef DEF_VISIT
185
186  // Main code generation function
187  void Generate(CompilationInfo* info, Mode mode);
188
189  struct InlineRuntimeLUT {
190    void (CodeGenerator::*method)(ZoneList<Expression*>*);
191    const char* name;
192  };
193
194  static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
195  bool CheckForInlineRuntimeCall(CallRuntime* node);
196  static bool PatchInlineRuntimeEntry(Handle<String> name,
197                                      const InlineRuntimeLUT& new_entry,
198                                      InlineRuntimeLUT* old_entry);
199
200  static Handle<Code> ComputeLazyCompile(int argc);
201  void ProcessDeclarations(ZoneList<Declaration*>* declarations);
202
203  Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
204
205  // Declare global variables and functions in the given array of
206  // name/value pairs.
207  void DeclareGlobals(Handle<FixedArray> pairs);
208
209  // Support for type checks.
210  void GenerateIsSmi(ZoneList<Expression*>* args);
211  void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
212  void GenerateIsArray(ZoneList<Expression*>* args);
213  void GenerateIsRegExp(ZoneList<Expression*>* args);
214
215  // Support for construct call checks.
216  void GenerateIsConstructCall(ZoneList<Expression*>* args);
217
218  // Support for arguments.length and arguments[?].
219  void GenerateArgumentsLength(ZoneList<Expression*>* args);
220  void GenerateArgumentsAccess(ZoneList<Expression*>* args);
221
222  // Support for accessing the class and value fields of an object.
223  void GenerateClassOf(ZoneList<Expression*>* args);
224  void GenerateValueOf(ZoneList<Expression*>* args);
225  void GenerateSetValueOf(ZoneList<Expression*>* args);
226
227  // Fast support for charCodeAt(n).
228  void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
229
230  // Fast support for object equality testing.
231  void GenerateObjectEquals(ZoneList<Expression*>* args);
232
233  void GenerateLog(ZoneList<Expression*>* args);
234
235  // Fast support for Math.random().
236  void GenerateRandomPositiveSmi(ZoneList<Expression*>* args);
237
238  void GenerateIsObject(ZoneList<Expression*>* args);
239  void GenerateIsFunction(ZoneList<Expression*>* args);
240  void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
241  void GenerateStringAdd(ZoneList<Expression*>* args);
242  void GenerateSubString(ZoneList<Expression*>* args);
243  void GenerateStringCompare(ZoneList<Expression*>* args);
244  void GenerateRegExpExec(ZoneList<Expression*>* args);
245  void GenerateNumberToString(ZoneList<Expression*>* args);
246
247
248  // Fast support for Math.sin and Math.cos.
249  inline void GenerateMathSin(ZoneList<Expression*>* args);
250  inline void GenerateMathCos(ZoneList<Expression*>* args);
251
252  // Simple condition analysis.
253  enum ConditionAnalysis {
254    ALWAYS_TRUE,
255    ALWAYS_FALSE,
256    DONT_KNOW
257  };
258  ConditionAnalysis AnalyzeCondition(Expression* cond);
259
260  // Methods used to indicate which source code is generated for. Source
261  // positions are collected by the assembler and emitted with the relocation
262  // information.
263  void CodeForFunctionPosition(FunctionLiteral* fun);
264  void CodeForReturnPosition(FunctionLiteral* fun);
265  void CodeForStatementPosition(Statement* node);
266  void CodeForDoWhileConditionPosition(DoWhileStatement* stmt);
267  void CodeForSourcePosition(int pos);
268
269#ifdef DEBUG
270  // True if the registers are valid for entry to a block.
271  bool HasValidEntryRegisters();
272#endif
273
274  bool is_eval_;  // Tells whether code is generated for eval.
275
276  Handle<Script> script_;
277  List<DeferredCode*> deferred_;
278
279  // Assembler
280  MacroAssembler* masm_;  // to generate code
281
282  CompilationInfo* info_;
283
284  // Code generation state
285  Scope* scope_;
286  VirtualFrame* frame_;
287  RegisterAllocator* allocator_;
288  Condition cc_reg_;
289  CodeGenState* state_;
290
291  // Jump targets
292  BreakTarget function_return_;
293
294  // True if the function return is shadowed (ie, jumping to the target
295  // function_return_ does not jump to the true function return, but rather
296  // to some unlinking code).
297  bool function_return_is_shadowed_;
298
299  static InlineRuntimeLUT kInlineRuntimeLUT[];
300
301  friend class VirtualFrame;
302  friend class JumpTarget;
303  friend class Reference;
304  friend class FastCodeGenerator;
305  friend class FullCodeGenSyntaxChecker;
306
307  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
308};
309
310
311} }  // namespace v8::internal
312
313#endif  // V8_MIPS_CODEGEN_MIPS_H_
314