codegen-arm.h revision 402d937239b0e2fd11bf2f4fe972ad78aa9fd481
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#ifndef V8_ARM_CODEGEN_ARM_H_
29#define V8_ARM_CODEGEN_ARM_H_
30
31namespace v8 {
32namespace internal {
33
34// Forward declarations
35class CompilationInfo;
36class DeferredCode;
37class RegisterAllocator;
38class RegisterFile;
39
40enum InitState { CONST_INIT, NOT_CONST_INIT };
41enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
42
43
44// -------------------------------------------------------------------------
45// Reference support
46
47// A reference is a C++ stack-allocated object that puts a
48// reference on the virtual frame.  The reference may be consumed
49// by GetValue, TakeValue, SetValue, and Codegen::UnloadReference.
50// When the lifetime (scope) of a valid reference ends, it must have
51// been consumed, and be in state UNLOADED.
52class Reference BASE_EMBEDDED {
53 public:
54  // The values of the types is important, see size().
55  enum Type { UNLOADED = -2, ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 };
56  Reference(CodeGenerator* cgen,
57            Expression* expression,
58            bool persist_after_get = false);
59  ~Reference();
60
61  Expression* expression() const { return expression_; }
62  Type type() const { return type_; }
63  void set_type(Type value) {
64    ASSERT_EQ(ILLEGAL, type_);
65    type_ = value;
66  }
67
68  void set_unloaded() {
69    ASSERT_NE(ILLEGAL, type_);
70    ASSERT_NE(UNLOADED, type_);
71    type_ = UNLOADED;
72  }
73  // The size the reference takes up on the stack.
74  int size() const {
75    return (type_ < SLOT) ? 0 : type_;
76  }
77
78  bool is_illegal() const { return type_ == ILLEGAL; }
79  bool is_slot() const { return type_ == SLOT; }
80  bool is_property() const { return type_ == NAMED || type_ == KEYED; }
81  bool is_unloaded() const { return type_ == UNLOADED; }
82
83  // Return the name.  Only valid for named property references.
84  Handle<String> GetName();
85
86  // Generate code to push the value of the reference on top of the
87  // expression stack.  The reference is expected to be already on top of
88  // the expression stack, and it is consumed by the call unless the
89  // reference is for a compound assignment.
90  // If the reference is not consumed, it is left in place under its value.
91  void GetValue();
92
93  // Generate code to pop a reference, push the value of the reference,
94  // and then spill the stack frame.
95  inline void GetValueAndSpill();
96
97  // Generate code to store the value on top of the expression stack in the
98  // reference.  The reference is expected to be immediately below the value
99  // on the expression stack.  The  value is stored in the location specified
100  // by the reference, and is left on top of the stack, after the reference
101  // is popped from beneath it (unloaded).
102  void SetValue(InitState init_state);
103
104 private:
105  CodeGenerator* cgen_;
106  Expression* expression_;
107  Type type_;
108  // Keep the reference on the stack after get, so it can be used by set later.
109  bool persist_after_get_;
110};
111
112
113// -------------------------------------------------------------------------
114// Code generation state
115
116// The state is passed down the AST by the code generator (and back up, in
117// the form of the state of the label pair).  It is threaded through the
118// call stack.  Constructing a state implicitly pushes it on the owning code
119// generator's stack of states, and destroying one implicitly pops it.
120
121class CodeGenState BASE_EMBEDDED {
122 public:
123  // Create an initial code generator state.  Destroying the initial state
124  // leaves the code generator with a NULL state.
125  explicit CodeGenState(CodeGenerator* owner);
126
127  // Create a code generator state based on a code generator's current
128  // state.  The new state has its own pair of branch labels.
129  CodeGenState(CodeGenerator* owner,
130               JumpTarget* true_target,
131               JumpTarget* false_target);
132
133  // Destroy a code generator state and restore the owning code generator's
134  // previous state.
135  ~CodeGenState();
136
137  JumpTarget* true_target() const { return true_target_; }
138  JumpTarget* false_target() const { return false_target_; }
139
140 private:
141  CodeGenerator* owner_;
142  JumpTarget* true_target_;
143  JumpTarget* false_target_;
144  CodeGenState* previous_;
145};
146
147
148// -------------------------------------------------------------------------
149// CodeGenerator
150
151class CodeGenerator: public AstVisitor {
152 public:
153  // Takes a function literal, generates code for it. This function should only
154  // be called by compiler.cc.
155  static Handle<Code> MakeCode(CompilationInfo* info);
156
157  // Printing of AST, etc. as requested by flags.
158  static void MakeCodePrologue(CompilationInfo* info);
159
160  // Allocate and install the code.
161  static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
162                                       Code::Flags flags,
163                                       CompilationInfo* info);
164
165#ifdef ENABLE_LOGGING_AND_PROFILING
166  static bool ShouldGenerateLog(Expression* type);
167#endif
168
169  static void SetFunctionInfo(Handle<JSFunction> fun,
170                              FunctionLiteral* lit,
171                              bool is_toplevel,
172                              Handle<Script> script);
173
174  static void RecordPositions(MacroAssembler* masm, int pos);
175
176  // Accessors
177  MacroAssembler* masm() { return masm_; }
178  VirtualFrame* frame() const { return frame_; }
179  inline Handle<Script> script();
180
181  bool has_valid_frame() const { return frame_ != NULL; }
182
183  // Set the virtual frame to be new_frame, with non-frame register
184  // reference counts given by non_frame_registers.  The non-frame
185  // register reference counts of the old frame are returned in
186  // non_frame_registers.
187  void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
188
189  void DeleteFrame();
190
191  RegisterAllocator* allocator() const { return allocator_; }
192
193  CodeGenState* state() { return state_; }
194  void set_state(CodeGenState* state) { state_ = state; }
195
196  void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
197
198  static const int kUnknownIntValue = -1;
199
200 private:
201  // Construction/Destruction
202  explicit CodeGenerator(MacroAssembler* masm);
203
204  // Accessors
205  inline bool is_eval();
206  Scope* scope();
207
208  // Generating deferred code.
209  void ProcessDeferred();
210
211  // State
212  bool has_cc() const  { return cc_reg_ != al; }
213  JumpTarget* true_target() const  { return state_->true_target(); }
214  JumpTarget* false_target() const  { return state_->false_target(); }
215
216  // We don't track loop nesting level on ARM yet.
217  int loop_nesting() const { return 0; }
218
219  // Node visitors.
220  void VisitStatements(ZoneList<Statement*>* statements);
221
222#define DEF_VISIT(type) \
223  void Visit##type(type* node);
224  AST_NODE_LIST(DEF_VISIT)
225#undef DEF_VISIT
226
227  // Visit a statement and then spill the virtual frame if control flow can
228  // reach the end of the statement (ie, it does not exit via break,
229  // continue, return, or throw).  This function is used temporarily while
230  // the code generator is being transformed.
231  inline void VisitAndSpill(Statement* statement);
232
233  // Visit a list of statements and then spill the virtual frame if control
234  // flow can reach the end of the list.
235  inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
236
237  // Main code generation function
238  void Generate(CompilationInfo* info);
239
240  // The following are used by class Reference.
241  void LoadReference(Reference* ref);
242  void UnloadReference(Reference* ref);
243
244  static MemOperand ContextOperand(Register context, int index) {
245    return MemOperand(context, Context::SlotOffset(index));
246  }
247
248  MemOperand SlotOperand(Slot* slot, Register tmp);
249
250  MemOperand ContextSlotOperandCheckExtensions(Slot* slot,
251                                               Register tmp,
252                                               Register tmp2,
253                                               JumpTarget* slow);
254
255  // Expressions
256  static MemOperand GlobalObject()  {
257    return ContextOperand(cp, Context::GLOBAL_INDEX);
258  }
259
260  void LoadCondition(Expression* x,
261                     JumpTarget* true_target,
262                     JumpTarget* false_target,
263                     bool force_cc);
264  void Load(Expression* expr);
265  void LoadGlobal();
266  void LoadGlobalReceiver(Register scratch);
267
268  // Generate code to push the value of an expression on top of the frame
269  // and then spill the frame fully to memory.  This function is used
270  // temporarily while the code generator is being transformed.
271  inline void LoadAndSpill(Expression* expression);
272
273  // Call LoadCondition and then spill the virtual frame unless control flow
274  // cannot reach the end of the expression (ie, by emitting only
275  // unconditional jumps to the control targets).
276  inline void LoadConditionAndSpill(Expression* expression,
277                                    JumpTarget* true_target,
278                                    JumpTarget* false_target,
279                                    bool force_control);
280
281  // Read a value from a slot and leave it on top of the expression stack.
282  void LoadFromSlot(Slot* slot, TypeofState typeof_state);
283  // Store the value on top of the stack to a slot.
284  void StoreToSlot(Slot* slot, InitState init_state);
285  // Load a keyed property, leaving it in r0.  The receiver and key are
286  // passed on the stack, and remain there.
287  void EmitKeyedLoad(bool is_global);
288
289  void LoadFromGlobalSlotCheckExtensions(Slot* slot,
290                                         TypeofState typeof_state,
291                                         Register tmp,
292                                         Register tmp2,
293                                         JumpTarget* slow);
294
295  // Special code for typeof expressions: Unfortunately, we must
296  // be careful when loading the expression in 'typeof'
297  // expressions. We are not allowed to throw reference errors for
298  // non-existing properties of the global object, so we must make it
299  // look like an explicit property access, instead of an access
300  // through the context chain.
301  void LoadTypeofExpression(Expression* x);
302
303  void ToBoolean(JumpTarget* true_target, JumpTarget* false_target);
304
305  void GenericBinaryOperation(Token::Value op,
306                              OverwriteMode overwrite_mode,
307                              int known_rhs = kUnknownIntValue);
308  void Comparison(Condition cc,
309                  Expression* left,
310                  Expression* right,
311                  bool strict = false);
312
313  void SmiOperation(Token::Value op,
314                    Handle<Object> value,
315                    bool reversed,
316                    OverwriteMode mode);
317
318  void CallWithArguments(ZoneList<Expression*>* arguments,
319                         CallFunctionFlags flags,
320                         int position);
321
322  // Control flow
323  void Branch(bool if_true, JumpTarget* target);
324  void CheckStack();
325
326  struct InlineRuntimeLUT {
327    void (CodeGenerator::*method)(ZoneList<Expression*>*);
328    const char* name;
329  };
330
331  static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
332  bool CheckForInlineRuntimeCall(CallRuntime* node);
333  static bool PatchInlineRuntimeEntry(Handle<String> name,
334                                      const InlineRuntimeLUT& new_entry,
335                                      InlineRuntimeLUT* old_entry);
336
337  static Handle<Code> ComputeLazyCompile(int argc);
338  void ProcessDeclarations(ZoneList<Declaration*>* declarations);
339
340  static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
341
342  // Declare global variables and functions in the given array of
343  // name/value pairs.
344  void DeclareGlobals(Handle<FixedArray> pairs);
345
346  // Instantiate the function boilerplate.
347  void InstantiateBoilerplate(Handle<JSFunction> boilerplate);
348
349  // Support for type checks.
350  void GenerateIsSmi(ZoneList<Expression*>* args);
351  void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
352  void GenerateIsArray(ZoneList<Expression*>* args);
353  void GenerateIsRegExp(ZoneList<Expression*>* args);
354  void GenerateIsObject(ZoneList<Expression*>* args);
355  void GenerateIsFunction(ZoneList<Expression*>* args);
356  void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
357
358  // Support for construct call checks.
359  void GenerateIsConstructCall(ZoneList<Expression*>* args);
360
361  // Support for arguments.length and arguments[?].
362  void GenerateArgumentsLength(ZoneList<Expression*>* args);
363  void GenerateArgumentsAccess(ZoneList<Expression*>* args);
364
365  // Support for accessing the class and value fields of an object.
366  void GenerateClassOf(ZoneList<Expression*>* args);
367  void GenerateValueOf(ZoneList<Expression*>* args);
368  void GenerateSetValueOf(ZoneList<Expression*>* args);
369
370  // Fast support for charCodeAt(n).
371  void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
372
373  // Fast support for object equality testing.
374  void GenerateObjectEquals(ZoneList<Expression*>* args);
375
376  void GenerateLog(ZoneList<Expression*>* args);
377
378  // Fast support for Math.random().
379  void GenerateRandomPositiveSmi(ZoneList<Expression*>* args);
380
381  // Fast support for StringAdd.
382  void GenerateStringAdd(ZoneList<Expression*>* args);
383
384  // Fast support for SubString.
385  void GenerateSubString(ZoneList<Expression*>* args);
386
387  // Fast support for StringCompare.
388  void GenerateStringCompare(ZoneList<Expression*>* args);
389
390  // Support for direct calls from JavaScript to native RegExp code.
391  void GenerateRegExpExec(ZoneList<Expression*>* args);
392
393  // Fast support for number to string.
394  void GenerateNumberToString(ZoneList<Expression*>* args);
395
396  // Fast call to sine function.
397  void GenerateMathSin(ZoneList<Expression*>* args);
398  void GenerateMathCos(ZoneList<Expression*>* args);
399
400  // Simple condition analysis.
401  enum ConditionAnalysis {
402    ALWAYS_TRUE,
403    ALWAYS_FALSE,
404    DONT_KNOW
405  };
406  ConditionAnalysis AnalyzeCondition(Expression* cond);
407
408  // Methods used to indicate which source code is generated for. Source
409  // positions are collected by the assembler and emitted with the relocation
410  // information.
411  void CodeForFunctionPosition(FunctionLiteral* fun);
412  void CodeForReturnPosition(FunctionLiteral* fun);
413  void CodeForStatementPosition(Statement* node);
414  void CodeForDoWhileConditionPosition(DoWhileStatement* stmt);
415  void CodeForSourcePosition(int pos);
416
417#ifdef DEBUG
418  // True if the registers are valid for entry to a block.
419  bool HasValidEntryRegisters();
420#endif
421
422  List<DeferredCode*> deferred_;
423
424  // Assembler
425  MacroAssembler* masm_;  // to generate code
426
427  CompilationInfo* info_;
428
429  // Code generation state
430  VirtualFrame* frame_;
431  RegisterAllocator* allocator_;
432  Condition cc_reg_;
433  CodeGenState* state_;
434
435  // Jump targets
436  BreakTarget function_return_;
437
438  // True if the function return is shadowed (ie, jumping to the target
439  // function_return_ does not jump to the true function return, but rather
440  // to some unlinking code).
441  bool function_return_is_shadowed_;
442
443  static InlineRuntimeLUT kInlineRuntimeLUT[];
444
445  friend class VirtualFrame;
446  friend class JumpTarget;
447  friend class Reference;
448  friend class FastCodeGenerator;
449  friend class FullCodeGenerator;
450  friend class FullCodeGenSyntaxChecker;
451
452  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
453};
454
455
456class GenericBinaryOpStub : public CodeStub {
457 public:
458  GenericBinaryOpStub(Token::Value op,
459                      OverwriteMode mode,
460                      int constant_rhs = CodeGenerator::kUnknownIntValue)
461      : op_(op),
462        mode_(mode),
463        constant_rhs_(constant_rhs),
464        specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)),
465        name_(NULL) { }
466
467 private:
468  Token::Value op_;
469  OverwriteMode mode_;
470  int constant_rhs_;
471  bool specialized_on_rhs_;
472  char* name_;
473
474  static const int kMaxKnownRhs = 0x40000000;
475
476  // Minor key encoding in 16 bits.
477  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
478  class OpBits: public BitField<Token::Value, 2, 6> {};
479  class KnownIntBits: public BitField<int, 8, 8> {};
480
481  Major MajorKey() { return GenericBinaryOp; }
482  int MinorKey() {
483    // Encode the parameters in a unique 16 bit value.
484    return OpBits::encode(op_)
485           | ModeBits::encode(mode_)
486           | KnownIntBits::encode(MinorKeyForKnownInt());
487  }
488
489  void Generate(MacroAssembler* masm);
490  void HandleNonSmiBitwiseOp(MacroAssembler* masm);
491
492  static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) {
493    if (constant_rhs == CodeGenerator::kUnknownIntValue) return false;
494    if (op == Token::DIV) return constant_rhs >= 2 && constant_rhs <= 3;
495    if (op == Token::MOD) {
496      if (constant_rhs <= 1) return false;
497      if (constant_rhs <= 10) return true;
498      if (constant_rhs <= kMaxKnownRhs && IsPowerOf2(constant_rhs)) return true;
499      return false;
500    }
501    return false;
502  }
503
504  int MinorKeyForKnownInt() {
505    if (!specialized_on_rhs_) return 0;
506    if (constant_rhs_ <= 10) return constant_rhs_ + 1;
507    ASSERT(IsPowerOf2(constant_rhs_));
508    int key = 12;
509    int d = constant_rhs_;
510    while ((d & 1) == 0) {
511      key++;
512      d >>= 1;
513    }
514    return key;
515  }
516
517  const char* GetName();
518
519#ifdef DEBUG
520  void Print() {
521    if (!specialized_on_rhs_) {
522      PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_));
523    } else {
524      PrintF("GenericBinaryOpStub (%s by %d)\n",
525             Token::String(op_),
526             constant_rhs_);
527    }
528  }
529#endif
530};
531
532
533class StringStubBase: public CodeStub {
534 public:
535  // Generate code for copying characters using a simple loop. This should only
536  // be used in places where the number of characters is small and the
537  // additional setup and checking in GenerateCopyCharactersLong adds too much
538  // overhead. Copying of overlapping regions is not supported.
539  // Dest register ends at the position after the last character written.
540  void GenerateCopyCharacters(MacroAssembler* masm,
541                              Register dest,
542                              Register src,
543                              Register count,
544                              Register scratch,
545                              bool ascii);
546
547  // Generate code for copying a large number of characters. This function
548  // is allowed to spend extra time setting up conditions to make copying
549  // faster. Copying of overlapping regions is not supported.
550  // Dest register ends at the position after the last character written.
551  void GenerateCopyCharactersLong(MacroAssembler* masm,
552                                  Register dest,
553                                  Register src,
554                                  Register count,
555                                  Register scratch1,
556                                  Register scratch2,
557                                  Register scratch3,
558                                  Register scratch4,
559                                  Register scratch5,
560                                  int flags);
561};
562
563
564// Flag that indicates how to generate code for the stub StringAddStub.
565enum StringAddFlags {
566  NO_STRING_ADD_FLAGS = 0,
567  NO_STRING_CHECK_IN_STUB = 1 << 0  // Omit string check in stub.
568};
569
570
571class StringAddStub: public StringStubBase {
572 public:
573  explicit StringAddStub(StringAddFlags flags) {
574    string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
575  }
576
577 private:
578  Major MajorKey() { return StringAdd; }
579  int MinorKey() { return string_check_ ? 0 : 1; }
580
581  void Generate(MacroAssembler* masm);
582
583  // Should the stub check whether arguments are strings?
584  bool string_check_;
585};
586
587
588class SubStringStub: public StringStubBase {
589 public:
590  SubStringStub() {}
591
592 private:
593  Major MajorKey() { return SubString; }
594  int MinorKey() { return 0; }
595
596  void Generate(MacroAssembler* masm);
597};
598
599
600
601class StringCompareStub: public CodeStub {
602 public:
603  StringCompareStub() { }
604
605  // Compare two flat ASCII strings and returns result in r0.
606  // Does not use the stack.
607  static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
608                                              Register left,
609                                              Register right,
610                                              Register scratch1,
611                                              Register scratch2,
612                                              Register scratch3,
613                                              Register scratch4);
614
615 private:
616  Major MajorKey() { return StringCompare; }
617  int MinorKey() { return 0; }
618
619  void Generate(MacroAssembler* masm);
620};
621
622
623} }  // namespace v8::internal
624
625#endif  // V8_ARM_CODEGEN_ARM_H_
626