codegen-mips.h revision 6ded16be15dd865a9b21ea304d5273c8be299c87
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// Reference support
47
48// A reference is a C++ stack-allocated object that keeps an ECMA
49// reference on the execution stack while in scope. For variables
50// the reference is empty, indicating that it isn't necessary to
51// store state on the stack for keeping track of references to those.
52// For properties, we keep either one (named) or two (indexed) values
53// on the execution stack to represent the reference.
54class Reference BASE_EMBEDDED {
55 public:
56  // The values of the types is important, see size().
57  enum Type { UNLOADED = -2, ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
58  Reference(CodeGenerator* cgen,
59            Expression* expression,
60            bool persist_after_get = false);
61  ~Reference();
62
63  Expression* expression() const { return expression_; }
64  Type type() const { return type_; }
65  void set_type(Type value) {
66    ASSERT_EQ(ILLEGAL, type_);
67    type_ = value;
68  }
69
70  void set_unloaded() {
71    ASSERT_NE(ILLEGAL, type_);
72    ASSERT_NE(UNLOADED, type_);
73    type_ = UNLOADED;
74  }
75  // The size the reference takes up on the stack.
76  int size() const {
77    return (type_ < SLOT) ? 0 : type_;
78  }
79
80  bool is_illegal() const { return type_ == ILLEGAL; }
81  bool is_slot() const { return type_ == SLOT; }
82  bool is_property() const { return type_ == NAMED || type_ == KEYED; }
83  bool is_unloaded() const { return type_ == UNLOADED; }
84
85  // Return the name. Only valid for named property references.
86  Handle<String> GetName();
87
88  // Generate code to push the value of the reference on top of the
89  // expression stack.  The reference is expected to be already on top of
90  // the expression stack, and it is consumed by the call unless the
91  // reference is for a compound assignment.
92  // If the reference is not consumed, it is left in place under its value.
93  void GetValue();
94
95  // Generate code to pop a reference, push the value of the reference,
96  // and then spill the stack frame.
97  inline void GetValueAndSpill();
98
99  // Generate code to store the value on top of the expression stack in the
100  // reference.  The reference is expected to be immediately below the value
101  // on the expression stack.  The  value is stored in the location specified
102  // by the reference, and is left on top of the stack, after the reference
103  // is popped from beneath it (unloaded).
104  void SetValue(InitState init_state);
105
106 private:
107  CodeGenerator* cgen_;
108  Expression* expression_;
109  Type type_;
110  // Keep the reference on the stack after get, so it can be used by set later.
111  bool persist_after_get_;
112};
113
114
115// -----------------------------------------------------------------------------
116// Code generation state
117
118// The state is passed down the AST by the code generator (and back up, in
119// the form of the state of the label pair).  It is threaded through the
120// call stack.  Constructing a state implicitly pushes it on the owning code
121// generator's stack of states, and destroying one implicitly pops it.
122
123class CodeGenState BASE_EMBEDDED {
124 public:
125  // Create an initial code generator state.  Destroying the initial state
126  // leaves the code generator with a NULL state.
127  explicit CodeGenState(CodeGenerator* owner);
128
129  // Create a code generator state based on a code generator's current
130  // state.  The new state has its own typeof state and pair of branch
131  // labels.
132  CodeGenState(CodeGenerator* owner,
133               JumpTarget* true_target,
134               JumpTarget* false_target);
135
136  // Destroy a code generator state and restore the owning code generator's
137  // previous state.
138  ~CodeGenState();
139
140  TypeofState typeof_state() const { return typeof_state_; }
141  JumpTarget* true_target() const { return true_target_; }
142  JumpTarget* false_target() const { return false_target_; }
143
144 private:
145  // The owning code generator.
146  CodeGenerator* owner_;
147
148  // A flag indicating whether we are compiling the immediate subexpression
149  // of a typeof expression.
150  TypeofState typeof_state_;
151
152  JumpTarget* true_target_;
153  JumpTarget* false_target_;
154
155  // The previous state of the owning code generator, restored when
156  // this state is destroyed.
157  CodeGenState* previous_;
158};
159
160
161
162// -----------------------------------------------------------------------------
163// CodeGenerator
164
165class CodeGenerator: public AstVisitor {
166 public:
167  // Compilation mode.  Either the compiler is used as the primary
168  // compiler and needs to setup everything or the compiler is used as
169  // the secondary compiler for split compilation and has to handle
170  // bailouts.
171  enum Mode {
172    PRIMARY,
173    SECONDARY
174  };
175
176  // Takes a function literal, generates code for it. This function should only
177  // be called by compiler.cc.
178  static Handle<Code> MakeCode(CompilationInfo* info);
179
180  // Printing of AST, etc. as requested by flags.
181  static void MakeCodePrologue(CompilationInfo* info);
182
183  // Allocate and install the code.
184  static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
185                                       Code::Flags flags,
186                                       CompilationInfo* info);
187
188#ifdef ENABLE_LOGGING_AND_PROFILING
189  static bool ShouldGenerateLog(Expression* type);
190#endif
191
192  static void SetFunctionInfo(Handle<JSFunction> fun,
193                              FunctionLiteral* lit,
194                              bool is_toplevel,
195                              Handle<Script> script);
196
197  static void RecordPositions(MacroAssembler* masm, int pos);
198
199  // Accessors
200  MacroAssembler* masm() { return masm_; }
201  VirtualFrame* frame() const { return frame_; }
202  inline Handle<Script> script();
203
204  bool has_valid_frame() const { return frame_ != NULL; }
205
206  // Set the virtual frame to be new_frame, with non-frame register
207  // reference counts given by non_frame_registers.  The non-frame
208  // register reference counts of the old frame are returned in
209  // non_frame_registers.
210  void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
211
212  void DeleteFrame();
213
214  RegisterAllocator* allocator() const { return allocator_; }
215
216  CodeGenState* state() { return state_; }
217  void set_state(CodeGenState* state) { state_ = state; }
218
219  void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
220
221  static const int kUnknownIntValue = -1;
222
223  // Number of instructions used for the JS return sequence. The constant is
224  // used by the debugger to patch the JS return sequence.
225  static const int kJSReturnSequenceLength = 7;
226
227  // If the name is an inline runtime function call return the number of
228  // expected arguments. Otherwise return -1.
229  static int InlineRuntimeCallArgumentsCount(Handle<String> name);
230
231 private:
232  // Construction/Destruction.
233  explicit CodeGenerator(MacroAssembler* masm);
234
235  // Accessors.
236  inline bool is_eval();
237  inline Scope* scope();
238
239  // Generating deferred code.
240  void ProcessDeferred();
241
242  // State
243  bool has_cc() const  { return cc_reg_ != cc_always; }
244  TypeofState typeof_state() const { return state_->typeof_state(); }
245  JumpTarget* true_target() const  { return state_->true_target(); }
246  JumpTarget* false_target() const  { return state_->false_target(); }
247
248  // We don't track loop nesting level on mips yet.
249  int loop_nesting() const { return 0; }
250
251  // Node visitors.
252  void VisitStatements(ZoneList<Statement*>* statements);
253
254#define DEF_VISIT(type) \
255  void Visit##type(type* node);
256  AST_NODE_LIST(DEF_VISIT)
257#undef DEF_VISIT
258
259  // Visit a statement and then spill the virtual frame if control flow can
260  // reach the end of the statement (ie, it does not exit via break,
261  // continue, return, or throw).  This function is used temporarily while
262  // the code generator is being transformed.
263  inline void VisitAndSpill(Statement* statement);
264
265  // Visit a list of statements and then spill the virtual frame if control
266  // flow can reach the end of the list.
267  inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
268
269  // Main code generation function
270  void Generate(CompilationInfo* info);
271
272  // The following are used by class Reference.
273  void LoadReference(Reference* ref);
274  void UnloadReference(Reference* ref);
275
276  MemOperand ContextOperand(Register context, int index) const {
277    return MemOperand(context, Context::SlotOffset(index));
278  }
279
280  MemOperand SlotOperand(Slot* slot, Register tmp);
281
282  // Expressions
283  MemOperand GlobalObject() const  {
284    return ContextOperand(cp, Context::GLOBAL_INDEX);
285  }
286
287  void LoadCondition(Expression* x,
288                     JumpTarget* true_target,
289                     JumpTarget* false_target,
290                     bool force_cc);
291  void Load(Expression* x);
292  void LoadGlobal();
293
294  // Generate code to push the value of an expression on top of the frame
295  // and then spill the frame fully to memory.  This function is used
296  // temporarily while the code generator is being transformed.
297  inline void LoadAndSpill(Expression* expression);
298
299  // Read a value from a slot and leave it on top of the expression stack.
300  void LoadFromSlot(Slot* slot, TypeofState typeof_state);
301  // Store the value on top of the stack to a slot.
302  void StoreToSlot(Slot* slot, InitState init_state);
303
304  struct InlineRuntimeLUT {
305    void (CodeGenerator::*method)(ZoneList<Expression*>*);
306    const char* name;
307    int nargs;
308  };
309
310  static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
311  bool CheckForInlineRuntimeCall(CallRuntime* node);
312  static bool PatchInlineRuntimeEntry(Handle<String> name,
313                                      const InlineRuntimeLUT& new_entry,
314                                      InlineRuntimeLUT* old_entry);
315
316  static Handle<Code> ComputeLazyCompile(int argc);
317  void ProcessDeclarations(ZoneList<Declaration*>* declarations);
318
319  Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
320
321  // Declare global variables and functions in the given array of
322  // name/value pairs.
323  void DeclareGlobals(Handle<FixedArray> pairs);
324
325  // Support for type checks.
326  void GenerateIsSmi(ZoneList<Expression*>* args);
327  void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
328  void GenerateIsArray(ZoneList<Expression*>* args);
329  void GenerateIsRegExp(ZoneList<Expression*>* args);
330
331  // Support for construct call checks.
332  void GenerateIsConstructCall(ZoneList<Expression*>* args);
333
334  // Support for arguments.length and arguments[?].
335  void GenerateArgumentsLength(ZoneList<Expression*>* args);
336  void GenerateArguments(ZoneList<Expression*>* args);
337
338  // Support for accessing the class and value fields of an object.
339  void GenerateClassOf(ZoneList<Expression*>* args);
340  void GenerateValueOf(ZoneList<Expression*>* args);
341  void GenerateSetValueOf(ZoneList<Expression*>* args);
342
343  // Fast support for charCodeAt(n).
344  void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
345
346  // Fast support for string.charAt(n) and string[n].
347  void GenerateCharFromCode(ZoneList<Expression*>* args);
348
349  // Fast support for object equality testing.
350  void GenerateObjectEquals(ZoneList<Expression*>* args);
351
352  void GenerateLog(ZoneList<Expression*>* args);
353
354  // Fast support for Math.random().
355  void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
356
357  void GenerateIsObject(ZoneList<Expression*>* args);
358  void GenerateIsFunction(ZoneList<Expression*>* args);
359  void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
360  void GenerateStringAdd(ZoneList<Expression*>* args);
361  void GenerateSubString(ZoneList<Expression*>* args);
362  void GenerateStringCompare(ZoneList<Expression*>* args);
363  void GenerateRegExpExec(ZoneList<Expression*>* args);
364  void GenerateNumberToString(ZoneList<Expression*>* args);
365
366  // Fast call to math functions.
367  void GenerateMathPow(ZoneList<Expression*>* args);
368  void GenerateMathSin(ZoneList<Expression*>* args);
369  void GenerateMathCos(ZoneList<Expression*>* args);
370  void GenerateMathSqrt(ZoneList<Expression*>* args);
371
372  // Simple condition analysis.
373  enum ConditionAnalysis {
374    ALWAYS_TRUE,
375    ALWAYS_FALSE,
376    DONT_KNOW
377  };
378  ConditionAnalysis AnalyzeCondition(Expression* cond);
379
380  // Methods used to indicate which source code is generated for. Source
381  // positions are collected by the assembler and emitted with the relocation
382  // information.
383  void CodeForFunctionPosition(FunctionLiteral* fun);
384  void CodeForReturnPosition(FunctionLiteral* fun);
385  void CodeForStatementPosition(Statement* node);
386  void CodeForDoWhileConditionPosition(DoWhileStatement* stmt);
387  void CodeForSourcePosition(int pos);
388
389#ifdef DEBUG
390  // True if the registers are valid for entry to a block.
391  bool HasValidEntryRegisters();
392#endif
393
394  bool is_eval_;  // Tells whether code is generated for eval.
395
396  Handle<Script> script_;
397  List<DeferredCode*> deferred_;
398
399  // Assembler
400  MacroAssembler* masm_;  // to generate code
401
402  CompilationInfo* info_;
403
404  // Code generation state
405  VirtualFrame* frame_;
406  RegisterAllocator* allocator_;
407  Condition cc_reg_;
408  CodeGenState* state_;
409
410  // Jump targets
411  BreakTarget function_return_;
412
413  // True if the function return is shadowed (ie, jumping to the target
414  // function_return_ does not jump to the true function return, but rather
415  // to some unlinking code).
416  bool function_return_is_shadowed_;
417
418  static InlineRuntimeLUT kInlineRuntimeLUT[];
419
420  friend class VirtualFrame;
421  friend class JumpTarget;
422  friend class Reference;
423  friend class FastCodeGenerator;
424  friend class FullCodeGenerator;
425  friend class FullCodeGenSyntaxChecker;
426
427  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
428};
429
430
431} }  // namespace v8::internal
432
433#endif  // V8_MIPS_CODEGEN_MIPS_H_
434