Add missing constant
[platform/upstream/v8.git] / src / arm / codegen-arm.h
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
31 #include "ic-inl.h"
32
33 namespace v8 {
34 namespace internal {
35
36 // Forward declarations
37 class CompilationInfo;
38 class DeferredCode;
39 class RegisterAllocator;
40 class RegisterFile;
41
42 enum InitState { CONST_INIT, NOT_CONST_INIT };
43 enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF };
44
45
46 // -------------------------------------------------------------------------
47 // Reference support
48
49 // A reference is a C++ stack-allocated object that puts a
50 // reference on the virtual frame.  The reference may be consumed
51 // by GetValue, TakeValue, SetValue, and Codegen::UnloadReference.
52 // When the lifetime (scope) of a valid reference ends, it must have
53 // been consumed, and be in state UNLOADED.
54 class 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 store the value on top of the expression stack in the
96   // reference.  The reference is expected to be immediately below the value
97   // on the expression stack.  The  value is stored in the location specified
98   // by the reference, and is left on top of the stack, after the reference
99   // is popped from beneath it (unloaded).
100   void SetValue(InitState init_state);
101
102  private:
103   CodeGenerator* cgen_;
104   Expression* expression_;
105   Type type_;
106   // Keep the reference on the stack after get, so it can be used by set later.
107   bool persist_after_get_;
108 };
109
110
111 // -------------------------------------------------------------------------
112 // Code generation state
113
114 // The state is passed down the AST by the code generator (and back up, in
115 // the form of the state of the label pair).  It is threaded through the
116 // call stack.  Constructing a state implicitly pushes it on the owning code
117 // generator's stack of states, and destroying one implicitly pops it.
118
119 class CodeGenState BASE_EMBEDDED {
120  public:
121   // Create an initial code generator state.  Destroying the initial state
122   // leaves the code generator with a NULL state.
123   explicit CodeGenState(CodeGenerator* owner);
124
125   // Create a code generator state based on a code generator's current
126   // state.  The new state has its own pair of branch labels.
127   CodeGenState(CodeGenerator* owner,
128                JumpTarget* true_target,
129                JumpTarget* false_target);
130
131   // Destroy a code generator state and restore the owning code generator's
132   // previous state.
133   ~CodeGenState();
134
135   JumpTarget* true_target() const { return true_target_; }
136   JumpTarget* false_target() const { return false_target_; }
137
138  private:
139   CodeGenerator* owner_;
140   JumpTarget* true_target_;
141   JumpTarget* false_target_;
142   CodeGenState* previous_;
143 };
144
145
146 // -------------------------------------------------------------------------
147 // Arguments allocation mode
148
149 enum ArgumentsAllocationMode {
150   NO_ARGUMENTS_ALLOCATION,
151   EAGER_ARGUMENTS_ALLOCATION,
152   LAZY_ARGUMENTS_ALLOCATION
153 };
154
155
156 // Different nop operations are used by the code generator to detect certain
157 // states of the generated code.
158 enum NopMarkerTypes {
159   NON_MARKING_NOP = 0,
160   PROPERTY_ACCESS_INLINED
161 };
162
163
164 // -------------------------------------------------------------------------
165 // CodeGenerator
166
167 class CodeGenerator: public AstVisitor {
168  public:
169   // Takes a function literal, generates code for it. This function should only
170   // be called by compiler.cc.
171   static Handle<Code> MakeCode(CompilationInfo* info);
172
173   // Printing of AST, etc. as requested by flags.
174   static void MakeCodePrologue(CompilationInfo* info);
175
176   // Allocate and install the code.
177   static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
178                                        Code::Flags flags,
179                                        CompilationInfo* info);
180
181 #ifdef ENABLE_LOGGING_AND_PROFILING
182   static bool ShouldGenerateLog(Expression* type);
183 #endif
184
185   static void SetFunctionInfo(Handle<JSFunction> fun,
186                               FunctionLiteral* lit,
187                               bool is_toplevel,
188                               Handle<Script> script);
189
190   static void RecordPositions(MacroAssembler* masm, int pos);
191
192   // Accessors
193   MacroAssembler* masm() { return masm_; }
194   VirtualFrame* frame() const { return frame_; }
195   inline Handle<Script> script();
196
197   bool has_valid_frame() const { return frame_ != NULL; }
198
199   // Set the virtual frame to be new_frame, with non-frame register
200   // reference counts given by non_frame_registers.  The non-frame
201   // register reference counts of the old frame are returned in
202   // non_frame_registers.
203   void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
204
205   void DeleteFrame();
206
207   RegisterAllocator* allocator() const { return allocator_; }
208
209   CodeGenState* state() { return state_; }
210   void set_state(CodeGenState* state) { state_ = state; }
211
212   void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
213
214   static const int kUnknownIntValue = -1;
215
216   // If the name is an inline runtime function call return the number of
217   // expected arguments. Otherwise return -1.
218   static int InlineRuntimeCallArgumentsCount(Handle<String> name);
219
220   // Constants related to patching of inlined lokad/store.
221   static const int kInlinedKeyedLoadInstructionsAfterPatchSize = 19;
222
223  private:
224   // Construction/Destruction
225   explicit CodeGenerator(MacroAssembler* masm);
226
227   // Accessors
228   inline bool is_eval();
229   inline Scope* scope();
230
231   // Generating deferred code.
232   void ProcessDeferred();
233
234   // State
235   bool has_cc() const  { return cc_reg_ != al; }
236   JumpTarget* true_target() const  { return state_->true_target(); }
237   JumpTarget* false_target() const  { return state_->false_target(); }
238
239   // Track loop nesting level.
240   int loop_nesting() const { return loop_nesting_; }
241   void IncrementLoopNesting() { loop_nesting_++; }
242   void DecrementLoopNesting() { loop_nesting_--; }
243
244   // Node visitors.
245   void VisitStatements(ZoneList<Statement*>* statements);
246
247 #define DEF_VISIT(type) \
248   void Visit##type(type* node);
249   AST_NODE_LIST(DEF_VISIT)
250 #undef DEF_VISIT
251
252   // Visit a statement and then spill the virtual frame if control flow can
253   // reach the end of the statement (ie, it does not exit via break,
254   // continue, return, or throw).  This function is used temporarily while
255   // the code generator is being transformed.
256   inline void VisitAndSpill(Statement* statement);
257
258   // Visit a list of statements and then spill the virtual frame if control
259   // flow can reach the end of the list.
260   inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
261
262   // Main code generation function
263   void Generate(CompilationInfo* info);
264
265   // Returns the arguments allocation mode.
266   ArgumentsAllocationMode ArgumentsMode();
267
268   // Store the arguments object and allocate it if necessary.
269   void StoreArgumentsObject(bool initial);
270
271   // The following are used by class Reference.
272   void LoadReference(Reference* ref);
273   void UnloadReference(Reference* ref);
274
275   static MemOperand ContextOperand(Register context, int index) {
276     return MemOperand(context, Context::SlotOffset(index));
277   }
278
279   MemOperand SlotOperand(Slot* slot, Register tmp);
280
281   MemOperand ContextSlotOperandCheckExtensions(Slot* slot,
282                                                Register tmp,
283                                                Register tmp2,
284                                                JumpTarget* slow);
285
286   // Expressions
287   static MemOperand GlobalObject()  {
288     return ContextOperand(cp, Context::GLOBAL_INDEX);
289   }
290
291   void LoadCondition(Expression* x,
292                      JumpTarget* true_target,
293                      JumpTarget* false_target,
294                      bool force_cc);
295   void Load(Expression* expr);
296   void LoadGlobal();
297   void LoadGlobalReceiver(Register scratch);
298
299   // Generate code to push the value of an expression on top of the frame
300   // and then spill the frame fully to memory.  This function is used
301   // temporarily while the code generator is being transformed.
302   inline void LoadAndSpill(Expression* expression);
303
304   // Call LoadCondition and then spill the virtual frame unless control flow
305   // cannot reach the end of the expression (ie, by emitting only
306   // unconditional jumps to the control targets).
307   inline void LoadConditionAndSpill(Expression* expression,
308                                     JumpTarget* true_target,
309                                     JumpTarget* false_target,
310                                     bool force_control);
311
312   // Read a value from a slot and leave it on top of the expression stack.
313   void LoadFromSlot(Slot* slot, TypeofState typeof_state);
314   void LoadFromSlotCheckForArguments(Slot* slot, TypeofState state);
315   // Store the value on top of the stack to a slot.
316   void StoreToSlot(Slot* slot, InitState init_state);
317
318   // Support for compiling assignment expressions.
319   void EmitSlotAssignment(Assignment* node);
320   void EmitNamedPropertyAssignment(Assignment* node);
321   void EmitKeyedPropertyAssignment(Assignment* node);
322
323   // Load a named property, returning it in r0. The receiver is passed on the
324   // stack, and remains there.
325   void EmitNamedLoad(Handle<String> name, bool is_contextual);
326
327   // Store to a named property. If the store is contextual, value is passed on
328   // the frame and consumed. Otherwise, receiver and value are passed on the
329   // frame and consumed. The result is returned in r0.
330   void EmitNamedStore(Handle<String> name, bool is_contextual);
331
332   // Load a keyed property, leaving it in r0.  The receiver and key are
333   // passed on the stack, and remain there.
334   void EmitKeyedLoad();
335
336   // Store a keyed property. Key and receiver are on the stack and the value is
337   // in r0. Result is returned in r0.
338   void EmitKeyedStore(StaticType* key_type);
339
340   void LoadFromGlobalSlotCheckExtensions(Slot* slot,
341                                          TypeofState typeof_state,
342                                          JumpTarget* slow);
343
344   // Special code for typeof expressions: Unfortunately, we must
345   // be careful when loading the expression in 'typeof'
346   // expressions. We are not allowed to throw reference errors for
347   // non-existing properties of the global object, so we must make it
348   // look like an explicit property access, instead of an access
349   // through the context chain.
350   void LoadTypeofExpression(Expression* x);
351
352   void ToBoolean(JumpTarget* true_target, JumpTarget* false_target);
353
354   // Generate code that computes a shortcutting logical operation.
355   void GenerateLogicalBooleanOperation(BinaryOperation* node);
356
357   void GenericBinaryOperation(Token::Value op,
358                               OverwriteMode overwrite_mode,
359                               int known_rhs = kUnknownIntValue);
360   void VirtualFrameBinaryOperation(Token::Value op,
361                                    OverwriteMode overwrite_mode,
362                                    int known_rhs = kUnknownIntValue);
363   void Comparison(Condition cc,
364                   Expression* left,
365                   Expression* right,
366                   bool strict = false);
367
368   void SmiOperation(Token::Value op,
369                     Handle<Object> value,
370                     bool reversed,
371                     OverwriteMode mode);
372
373   void CallWithArguments(ZoneList<Expression*>* arguments,
374                          CallFunctionFlags flags,
375                          int position);
376
377   // An optimized implementation of expressions of the form
378   // x.apply(y, arguments).  We call x the applicand and y the receiver.
379   // The optimization avoids allocating an arguments object if possible.
380   void CallApplyLazy(Expression* applicand,
381                      Expression* receiver,
382                      VariableProxy* arguments,
383                      int position);
384
385   // Control flow
386   void Branch(bool if_true, JumpTarget* target);
387   void CheckStack();
388
389   struct InlineRuntimeLUT {
390     void (CodeGenerator::*method)(ZoneList<Expression*>*);
391     const char* name;
392     int nargs;
393   };
394
395   static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
396   bool CheckForInlineRuntimeCall(CallRuntime* node);
397   static bool PatchInlineRuntimeEntry(Handle<String> name,
398                                       const InlineRuntimeLUT& new_entry,
399                                       InlineRuntimeLUT* old_entry);
400
401   static Handle<Code> ComputeLazyCompile(int argc);
402   void ProcessDeclarations(ZoneList<Declaration*>* declarations);
403
404   static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
405
406   // Declare global variables and functions in the given array of
407   // name/value pairs.
408   void DeclareGlobals(Handle<FixedArray> pairs);
409
410   // Instantiate the function based on the shared function info.
411   void InstantiateFunction(Handle<SharedFunctionInfo> function_info);
412
413   // Support for type checks.
414   void GenerateIsSmi(ZoneList<Expression*>* args);
415   void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
416   void GenerateIsArray(ZoneList<Expression*>* args);
417   void GenerateIsRegExp(ZoneList<Expression*>* args);
418   void GenerateIsObject(ZoneList<Expression*>* args);
419   void GenerateIsFunction(ZoneList<Expression*>* args);
420   void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
421
422   // Support for construct call checks.
423   void GenerateIsConstructCall(ZoneList<Expression*>* args);
424
425   // Support for arguments.length and arguments[?].
426   void GenerateArgumentsLength(ZoneList<Expression*>* args);
427   void GenerateArguments(ZoneList<Expression*>* args);
428
429   // Support for accessing the class and value fields of an object.
430   void GenerateClassOf(ZoneList<Expression*>* args);
431   void GenerateValueOf(ZoneList<Expression*>* args);
432   void GenerateSetValueOf(ZoneList<Expression*>* args);
433
434   // Fast support for charCodeAt(n).
435   void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
436
437   // Fast support for string.charAt(n) and string[n].
438   void GenerateCharFromCode(ZoneList<Expression*>* args);
439
440   // Fast support for object equality testing.
441   void GenerateObjectEquals(ZoneList<Expression*>* args);
442
443   void GenerateLog(ZoneList<Expression*>* args);
444
445   // Fast support for Math.random().
446   void GenerateRandomHeapNumber(ZoneList<Expression*>* args);
447
448   // Fast support for StringAdd.
449   void GenerateStringAdd(ZoneList<Expression*>* args);
450
451   // Fast support for SubString.
452   void GenerateSubString(ZoneList<Expression*>* args);
453
454   // Fast support for StringCompare.
455   void GenerateStringCompare(ZoneList<Expression*>* args);
456
457   // Support for direct calls from JavaScript to native RegExp code.
458   void GenerateRegExpExec(ZoneList<Expression*>* args);
459
460   void GenerateRegExpConstructResult(ZoneList<Expression*>* args);
461
462   // Support for fast native caches.
463   void GenerateGetFromCache(ZoneList<Expression*>* args);
464
465   // Fast support for number to string.
466   void GenerateNumberToString(ZoneList<Expression*>* args);
467
468   // Fast swapping of elements.
469   void GenerateSwapElements(ZoneList<Expression*>* args);
470
471   // Fast call for custom callbacks.
472   void GenerateCallFunction(ZoneList<Expression*>* args);
473
474   // Fast call to math functions.
475   void GenerateMathPow(ZoneList<Expression*>* args);
476   void GenerateMathSin(ZoneList<Expression*>* args);
477   void GenerateMathCos(ZoneList<Expression*>* args);
478   void GenerateMathSqrt(ZoneList<Expression*>* args);
479
480   // Simple condition analysis.
481   enum ConditionAnalysis {
482     ALWAYS_TRUE,
483     ALWAYS_FALSE,
484     DONT_KNOW
485   };
486   ConditionAnalysis AnalyzeCondition(Expression* cond);
487
488   // Methods used to indicate which source code is generated for. Source
489   // positions are collected by the assembler and emitted with the relocation
490   // information.
491   void CodeForFunctionPosition(FunctionLiteral* fun);
492   void CodeForReturnPosition(FunctionLiteral* fun);
493   void CodeForStatementPosition(Statement* node);
494   void CodeForDoWhileConditionPosition(DoWhileStatement* stmt);
495   void CodeForSourcePosition(int pos);
496
497 #ifdef DEBUG
498   // True if the registers are valid for entry to a block.
499   bool HasValidEntryRegisters();
500 #endif
501
502   List<DeferredCode*> deferred_;
503
504   // Assembler
505   MacroAssembler* masm_;  // to generate code
506
507   CompilationInfo* info_;
508
509   // Code generation state
510   VirtualFrame* frame_;
511   RegisterAllocator* allocator_;
512   Condition cc_reg_;
513   CodeGenState* state_;
514   int loop_nesting_;
515
516   // Jump targets
517   BreakTarget function_return_;
518
519   // True if the function return is shadowed (ie, jumping to the target
520   // function_return_ does not jump to the true function return, but rather
521   // to some unlinking code).
522   bool function_return_is_shadowed_;
523
524   static InlineRuntimeLUT kInlineRuntimeLUT[];
525
526   friend class VirtualFrame;
527   friend class JumpTarget;
528   friend class Reference;
529   friend class FastCodeGenerator;
530   friend class FullCodeGenerator;
531   friend class FullCodeGenSyntaxChecker;
532
533   DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
534 };
535
536
537 class GenericBinaryOpStub : public CodeStub {
538  public:
539   GenericBinaryOpStub(Token::Value op,
540                       OverwriteMode mode,
541                       Register lhs,
542                       Register rhs,
543                       int constant_rhs = CodeGenerator::kUnknownIntValue)
544       : op_(op),
545         mode_(mode),
546         lhs_(lhs),
547         rhs_(rhs),
548         constant_rhs_(constant_rhs),
549         specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op, constant_rhs)),
550         runtime_operands_type_(BinaryOpIC::DEFAULT),
551         name_(NULL) { }
552
553   GenericBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info)
554       : op_(OpBits::decode(key)),
555         mode_(ModeBits::decode(key)),
556         lhs_(LhsRegister(RegisterBits::decode(key))),
557         rhs_(RhsRegister(RegisterBits::decode(key))),
558         constant_rhs_(KnownBitsForMinorKey(KnownIntBits::decode(key))),
559         specialized_on_rhs_(RhsIsOneWeWantToOptimizeFor(op_, constant_rhs_)),
560         runtime_operands_type_(type_info),
561         name_(NULL) { }
562
563  private:
564   Token::Value op_;
565   OverwriteMode mode_;
566   Register lhs_;
567   Register rhs_;
568   int constant_rhs_;
569   bool specialized_on_rhs_;
570   BinaryOpIC::TypeInfo runtime_operands_type_;
571   char* name_;
572
573   static const int kMaxKnownRhs = 0x40000000;
574   static const int kKnownRhsKeyBits = 6;
575
576   // Minor key encoding in 17 bits.
577   class ModeBits: public BitField<OverwriteMode, 0, 2> {};
578   class OpBits: public BitField<Token::Value, 2, 6> {};
579   class TypeInfoBits: public BitField<int, 8, 2> {};
580   class RegisterBits: public BitField<bool, 10, 1> {};
581   class KnownIntBits: public BitField<int, 11, kKnownRhsKeyBits> {};
582
583   Major MajorKey() { return GenericBinaryOp; }
584   int MinorKey() {
585     ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
586            (lhs_.is(r1) && rhs_.is(r0)));
587     // Encode the parameters in a unique 18 bit value.
588     return OpBits::encode(op_)
589            | ModeBits::encode(mode_)
590            | KnownIntBits::encode(MinorKeyForKnownInt())
591            | TypeInfoBits::encode(runtime_operands_type_)
592            | RegisterBits::encode(lhs_.is(r0));
593   }
594
595   void Generate(MacroAssembler* masm);
596   void HandleNonSmiBitwiseOp(MacroAssembler* masm, Register lhs, Register rhs);
597   void HandleBinaryOpSlowCases(MacroAssembler* masm,
598                                Label* not_smi,
599                                Register lhs,
600                                Register rhs,
601                                const Builtins::JavaScript& builtin);
602   void GenerateTypeTransition(MacroAssembler* masm);
603
604   static bool RhsIsOneWeWantToOptimizeFor(Token::Value op, int constant_rhs) {
605     if (constant_rhs == CodeGenerator::kUnknownIntValue) return false;
606     if (op == Token::DIV) return constant_rhs >= 2 && constant_rhs <= 3;
607     if (op == Token::MOD) {
608       if (constant_rhs <= 1) return false;
609       if (constant_rhs <= 10) return true;
610       if (constant_rhs <= kMaxKnownRhs && IsPowerOf2(constant_rhs)) return true;
611       return false;
612     }
613     return false;
614   }
615
616   int MinorKeyForKnownInt() {
617     if (!specialized_on_rhs_) return 0;
618     if (constant_rhs_ <= 10) return constant_rhs_ + 1;
619     ASSERT(IsPowerOf2(constant_rhs_));
620     int key = 12;
621     int d = constant_rhs_;
622     while ((d & 1) == 0) {
623       key++;
624       d >>= 1;
625     }
626     ASSERT(key >= 0 && key < (1 << kKnownRhsKeyBits));
627     return key;
628   }
629
630   int KnownBitsForMinorKey(int key) {
631     if (!key) return 0;
632     if (key <= 11) return key - 1;
633     int d = 1;
634     while (key != 12) {
635       key--;
636       d <<= 1;
637     }
638     return d;
639   }
640
641   Register LhsRegister(bool lhs_is_r0) {
642     return lhs_is_r0 ? r0 : r1;
643   }
644
645   Register RhsRegister(bool lhs_is_r0) {
646     return lhs_is_r0 ? r1 : r0;
647   }
648
649   bool ShouldGenerateSmiCode() {
650     return ((op_ != Token::DIV && op_ != Token::MOD) || specialized_on_rhs_) &&
651         runtime_operands_type_ != BinaryOpIC::HEAP_NUMBERS &&
652         runtime_operands_type_ != BinaryOpIC::STRINGS;
653   }
654
655   bool ShouldGenerateFPCode() {
656     return runtime_operands_type_ != BinaryOpIC::STRINGS;
657   }
658
659   virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
660
661   virtual InlineCacheState GetICState() {
662     return BinaryOpIC::ToState(runtime_operands_type_);
663   }
664
665   const char* GetName();
666
667 #ifdef DEBUG
668   void Print() {
669     if (!specialized_on_rhs_) {
670       PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_));
671     } else {
672       PrintF("GenericBinaryOpStub (%s by %d)\n",
673              Token::String(op_),
674              constant_rhs_);
675     }
676   }
677 #endif
678 };
679
680
681 class StringHelper : public AllStatic {
682  public:
683   // Generates fast code for getting a char code out of a string
684   // object at the given index. May bail out for four reasons (in the
685   // listed order):
686   //   * Receiver is not a string (receiver_not_string label).
687   //   * Index is not a smi (index_not_smi label).
688   //   * Index is out of range (index_out_of_range).
689   //   * Some other reason (slow_case label). In this case it's
690   //     guaranteed that the above conditions are not violated,
691   //     e.g. it's safe to assume the receiver is a string and the
692   //     index is a non-negative smi < length.
693   // When successful, object, index, and scratch are clobbered.
694   // Otherwise, scratch and result are clobbered.
695   static void GenerateFastCharCodeAt(MacroAssembler* masm,
696                                      Register object,
697                                      Register index,
698                                      Register scratch,
699                                      Register result,
700                                      Label* receiver_not_string,
701                                      Label* index_not_smi,
702                                      Label* index_out_of_range,
703                                      Label* slow_case);
704
705   // Generates code for creating a one-char string from the given char
706   // code. May do a runtime call, so any register can be clobbered
707   // and, if the given invoke flag specifies a call, an internal frame
708   // is required. In tail call mode the result must be r0 register.
709   static void GenerateCharFromCode(MacroAssembler* masm,
710                                    Register code,
711                                    Register scratch,
712                                    Register result,
713                                    InvokeFlag flag);
714
715   // Generate code for copying characters using a simple loop. This should only
716   // be used in places where the number of characters is small and the
717   // additional setup and checking in GenerateCopyCharactersLong adds too much
718   // overhead. Copying of overlapping regions is not supported.
719   // Dest register ends at the position after the last character written.
720   static void GenerateCopyCharacters(MacroAssembler* masm,
721                                      Register dest,
722                                      Register src,
723                                      Register count,
724                                      Register scratch,
725                                      bool ascii);
726
727   // Generate code for copying a large number of characters. This function
728   // is allowed to spend extra time setting up conditions to make copying
729   // faster. Copying of overlapping regions is not supported.
730   // Dest register ends at the position after the last character written.
731   static void GenerateCopyCharactersLong(MacroAssembler* masm,
732                                          Register dest,
733                                          Register src,
734                                          Register count,
735                                          Register scratch1,
736                                          Register scratch2,
737                                          Register scratch3,
738                                          Register scratch4,
739                                          Register scratch5,
740                                          int flags);
741
742
743   // Probe the symbol table for a two character string. If the string is
744   // not found by probing a jump to the label not_found is performed. This jump
745   // does not guarantee that the string is not in the symbol table. If the
746   // string is found the code falls through with the string in register r0.
747   // Contents of both c1 and c2 registers are modified. At the exit c1 is
748   // guaranteed to contain halfword with low and high bytes equal to
749   // initial contents of c1 and c2 respectively.
750   static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
751                                                    Register c1,
752                                                    Register c2,
753                                                    Register scratch1,
754                                                    Register scratch2,
755                                                    Register scratch3,
756                                                    Register scratch4,
757                                                    Register scratch5,
758                                                    Label* not_found);
759
760   // Generate string hash.
761   static void GenerateHashInit(MacroAssembler* masm,
762                                Register hash,
763                                Register character);
764
765   static void GenerateHashAddCharacter(MacroAssembler* masm,
766                                        Register hash,
767                                        Register character);
768
769   static void GenerateHashGetHash(MacroAssembler* masm,
770                                   Register hash);
771
772  private:
773   DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
774 };
775
776
777 // Flag that indicates how to generate code for the stub StringAddStub.
778 enum StringAddFlags {
779   NO_STRING_ADD_FLAGS = 0,
780   NO_STRING_CHECK_IN_STUB = 1 << 0  // Omit string check in stub.
781 };
782
783
784 class StringAddStub: public CodeStub {
785  public:
786   explicit StringAddStub(StringAddFlags flags) {
787     string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
788   }
789
790  private:
791   Major MajorKey() { return StringAdd; }
792   int MinorKey() { return string_check_ ? 0 : 1; }
793
794   void Generate(MacroAssembler* masm);
795
796   // Should the stub check whether arguments are strings?
797   bool string_check_;
798 };
799
800
801 class SubStringStub: public CodeStub {
802  public:
803   SubStringStub() {}
804
805  private:
806   Major MajorKey() { return SubString; }
807   int MinorKey() { return 0; }
808
809   void Generate(MacroAssembler* masm);
810 };
811
812
813
814 class StringCompareStub: public CodeStub {
815  public:
816   StringCompareStub() { }
817
818   // Compare two flat ASCII strings and returns result in r0.
819   // Does not use the stack.
820   static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
821                                               Register left,
822                                               Register right,
823                                               Register scratch1,
824                                               Register scratch2,
825                                               Register scratch3,
826                                               Register scratch4);
827
828  private:
829   Major MajorKey() { return StringCompare; }
830   int MinorKey() { return 0; }
831
832   void Generate(MacroAssembler* masm);
833 };
834
835
836 // This stub can convert a signed int32 to a heap number (double).  It does
837 // not work for int32s that are in Smi range!  No GC occurs during this stub
838 // so you don't have to set up the frame.
839 class WriteInt32ToHeapNumberStub : public CodeStub {
840  public:
841   WriteInt32ToHeapNumberStub(Register the_int,
842                              Register the_heap_number,
843                              Register scratch)
844       : the_int_(the_int),
845         the_heap_number_(the_heap_number),
846         scratch_(scratch) { }
847
848  private:
849   Register the_int_;
850   Register the_heap_number_;
851   Register scratch_;
852
853   // Minor key encoding in 16 bits.
854   class IntRegisterBits: public BitField<int, 0, 4> {};
855   class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
856   class ScratchRegisterBits: public BitField<int, 8, 4> {};
857
858   Major MajorKey() { return WriteInt32ToHeapNumber; }
859   int MinorKey() {
860     // Encode the parameters in a unique 16 bit value.
861     return IntRegisterBits::encode(the_int_.code())
862            | HeapNumberRegisterBits::encode(the_heap_number_.code())
863            | ScratchRegisterBits::encode(scratch_.code());
864   }
865
866   void Generate(MacroAssembler* masm);
867
868   const char* GetName() { return "WriteInt32ToHeapNumberStub"; }
869
870 #ifdef DEBUG
871   void Print() { PrintF("WriteInt32ToHeapNumberStub\n"); }
872 #endif
873 };
874
875
876 class NumberToStringStub: public CodeStub {
877  public:
878   NumberToStringStub() { }
879
880   // Generate code to do a lookup in the number string cache. If the number in
881   // the register object is found in the cache the generated code falls through
882   // with the result in the result register. The object and the result register
883   // can be the same. If the number is not found in the cache the code jumps to
884   // the label not_found with only the content of register object unchanged.
885   static void GenerateLookupNumberStringCache(MacroAssembler* masm,
886                                               Register object,
887                                               Register result,
888                                               Register scratch1,
889                                               Register scratch2,
890                                               Register scratch3,
891                                               bool object_is_smi,
892                                               Label* not_found);
893
894  private:
895   Major MajorKey() { return NumberToString; }
896   int MinorKey() { return 0; }
897
898   void Generate(MacroAssembler* masm);
899
900   const char* GetName() { return "NumberToStringStub"; }
901
902 #ifdef DEBUG
903   void Print() {
904     PrintF("NumberToStringStub\n");
905   }
906 #endif
907 };
908
909
910 class RecordWriteStub : public CodeStub {
911  public:
912   RecordWriteStub(Register object, Register offset, Register scratch)
913       : object_(object), offset_(offset), scratch_(scratch) { }
914
915   void Generate(MacroAssembler* masm);
916
917  private:
918   Register object_;
919   Register offset_;
920   Register scratch_;
921
922 #ifdef DEBUG
923   void Print() {
924     PrintF("RecordWriteStub (object reg %d), (offset reg %d),"
925            " (scratch reg %d)\n",
926            object_.code(), offset_.code(), scratch_.code());
927   }
928 #endif
929
930   // Minor key encoding in 12 bits. 4 bits for each of the three
931   // registers (object, offset and scratch) OOOOAAAASSSS.
932   class ScratchBits: public BitField<uint32_t, 0, 4> {};
933   class OffsetBits: public BitField<uint32_t, 4, 4> {};
934   class ObjectBits: public BitField<uint32_t, 8, 4> {};
935
936   Major MajorKey() { return RecordWrite; }
937
938   int MinorKey() {
939     // Encode the registers.
940     return ObjectBits::encode(object_.code()) |
941            OffsetBits::encode(offset_.code()) |
942            ScratchBits::encode(scratch_.code());
943   }
944 };
945
946
947 } }  // namespace v8::internal
948
949 #endif  // V8_ARM_CODEGEN_ARM_H_