codegen-ia32.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_IA32_CODEGEN_IA32_H_
29#define V8_IA32_CODEGEN_IA32_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  // Like GetValue except that the slot is expected to be written to before
94  // being read from again.  The value of the reference may be invalidated,
95  // causing subsequent attempts to read it to fail.
96  void TakeValue();
97
98  // Generate code to store the value on top of the expression stack in the
99  // reference.  The reference is expected to be immediately below the value
100  // on the expression stack.  The  value is stored in the location specified
101  // by the reference, and is left on top of the stack, after the reference
102  // is popped from beneath it (unloaded).
103  void SetValue(InitState init_state);
104
105 private:
106  CodeGenerator* cgen_;
107  Expression* expression_;
108  Type type_;
109  // Keep the reference on the stack after get, so it can be used by set later.
110  bool persist_after_get_;
111};
112
113
114// -------------------------------------------------------------------------
115// Control destinations.
116
117// A control destination encapsulates a pair of jump targets and a
118// flag indicating which one is the preferred fall-through.  The
119// preferred fall-through must be unbound, the other may be already
120// bound (ie, a backward target).
121//
122// The true and false targets may be jumped to unconditionally or
123// control may split conditionally.  Unconditional jumping and
124// splitting should be emitted in tail position (as the last thing
125// when compiling an expression) because they can cause either label
126// to be bound or the non-fall through to be jumped to leaving an
127// invalid virtual frame.
128//
129// The labels in the control destination can be extracted and
130// manipulated normally without affecting the state of the
131// destination.
132
133class ControlDestination BASE_EMBEDDED {
134 public:
135  ControlDestination(JumpTarget* true_target,
136                     JumpTarget* false_target,
137                     bool true_is_fall_through)
138      : true_target_(true_target),
139        false_target_(false_target),
140        true_is_fall_through_(true_is_fall_through),
141        is_used_(false) {
142    ASSERT(true_is_fall_through ? !true_target->is_bound()
143                                : !false_target->is_bound());
144  }
145
146  // Accessors for the jump targets.  Directly jumping or branching to
147  // or binding the targets will not update the destination's state.
148  JumpTarget* true_target() const { return true_target_; }
149  JumpTarget* false_target() const { return false_target_; }
150
151  // True if the the destination has been jumped to unconditionally or
152  // control has been split to both targets.  This predicate does not
153  // test whether the targets have been extracted and manipulated as
154  // raw jump targets.
155  bool is_used() const { return is_used_; }
156
157  // True if the destination is used and the true target (respectively
158  // false target) was the fall through.  If the target is backward,
159  // "fall through" included jumping unconditionally to it.
160  bool true_was_fall_through() const {
161    return is_used_ && true_is_fall_through_;
162  }
163
164  bool false_was_fall_through() const {
165    return is_used_ && !true_is_fall_through_;
166  }
167
168  // Emit a branch to one of the true or false targets, and bind the
169  // other target.  Because this binds the fall-through target, it
170  // should be emitted in tail position (as the last thing when
171  // compiling an expression).
172  void Split(Condition cc) {
173    ASSERT(!is_used_);
174    if (true_is_fall_through_) {
175      false_target_->Branch(NegateCondition(cc));
176      true_target_->Bind();
177    } else {
178      true_target_->Branch(cc);
179      false_target_->Bind();
180    }
181    is_used_ = true;
182  }
183
184  // Emit an unconditional jump in tail position, to the true target
185  // (if the argument is true) or the false target.  The "jump" will
186  // actually bind the jump target if it is forward, jump to it if it
187  // is backward.
188  void Goto(bool where) {
189    ASSERT(!is_used_);
190    JumpTarget* target = where ? true_target_ : false_target_;
191    if (target->is_bound()) {
192      target->Jump();
193    } else {
194      target->Bind();
195    }
196    is_used_ = true;
197    true_is_fall_through_ = where;
198  }
199
200  // Mark this jump target as used as if Goto had been called, but
201  // without generating a jump or binding a label (the control effect
202  // should have already happened).  This is used when the left
203  // subexpression of the short-circuit boolean operators are
204  // compiled.
205  void Use(bool where) {
206    ASSERT(!is_used_);
207    ASSERT((where ? true_target_ : false_target_)->is_bound());
208    is_used_ = true;
209    true_is_fall_through_ = where;
210  }
211
212  // Swap the true and false targets but keep the same actual label as
213  // the fall through.  This is used when compiling negated
214  // expressions, where we want to swap the targets but preserve the
215  // state.
216  void Invert() {
217    JumpTarget* temp_target = true_target_;
218    true_target_ = false_target_;
219    false_target_ = temp_target;
220
221    true_is_fall_through_ = !true_is_fall_through_;
222  }
223
224 private:
225  // True and false jump targets.
226  JumpTarget* true_target_;
227  JumpTarget* false_target_;
228
229  // Before using the destination: true if the true target is the
230  // preferred fall through, false if the false target is.  After
231  // using the destination: true if the true target was actually used
232  // as the fall through, false if the false target was.
233  bool true_is_fall_through_;
234
235  // True if the Split or Goto functions have been called.
236  bool is_used_;
237};
238
239
240// -------------------------------------------------------------------------
241// Code generation state
242
243// The state is passed down the AST by the code generator (and back up, in
244// the form of the state of the jump target pair).  It is threaded through
245// the call stack.  Constructing a state implicitly pushes it on the owning
246// code generator's stack of states, and destroying one implicitly pops it.
247//
248// The code generator state is only used for expressions, so statements have
249// the initial state.
250
251class CodeGenState BASE_EMBEDDED {
252 public:
253  // Create an initial code generator state.  Destroying the initial state
254  // leaves the code generator with a NULL state.
255  explicit CodeGenState(CodeGenerator* owner);
256
257  // Create a code generator state based on a code generator's current
258  // state.  The new state has its own control destination.
259  CodeGenState(CodeGenerator* owner, ControlDestination* destination);
260
261  // Destroy a code generator state and restore the owning code generator's
262  // previous state.
263  ~CodeGenState();
264
265  // Accessors for the state.
266  ControlDestination* destination() const { return destination_; }
267
268 private:
269  // The owning code generator.
270  CodeGenerator* owner_;
271
272  // A control destination in case the expression has a control-flow
273  // effect.
274  ControlDestination* destination_;
275
276  // The previous state of the owning code generator, restored when
277  // this state is destroyed.
278  CodeGenState* previous_;
279};
280
281
282// -------------------------------------------------------------------------
283// Arguments allocation mode.
284
285enum ArgumentsAllocationMode {
286  NO_ARGUMENTS_ALLOCATION,
287  EAGER_ARGUMENTS_ALLOCATION,
288  LAZY_ARGUMENTS_ALLOCATION
289};
290
291
292// -------------------------------------------------------------------------
293// CodeGenerator
294
295class CodeGenerator: public AstVisitor {
296 public:
297  // Takes a function literal, generates code for it. This function should only
298  // be called by compiler.cc.
299  static Handle<Code> MakeCode(CompilationInfo* info);
300
301  // Printing of AST, etc. as requested by flags.
302  static void MakeCodePrologue(CompilationInfo* info);
303
304  // Allocate and install the code.
305  static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
306                                       Code::Flags flags,
307                                       CompilationInfo* info);
308
309#ifdef ENABLE_LOGGING_AND_PROFILING
310  static bool ShouldGenerateLog(Expression* type);
311#endif
312
313  static void RecordPositions(MacroAssembler* masm, int pos);
314
315  // Accessors
316  MacroAssembler* masm() { return masm_; }
317  VirtualFrame* frame() const { return frame_; }
318  inline Handle<Script> script();
319
320  bool has_valid_frame() const { return frame_ != NULL; }
321
322  // Set the virtual frame to be new_frame, with non-frame register
323  // reference counts given by non_frame_registers.  The non-frame
324  // register reference counts of the old frame are returned in
325  // non_frame_registers.
326  void SetFrame(VirtualFrame* new_frame, RegisterFile* non_frame_registers);
327
328  void DeleteFrame();
329
330  RegisterAllocator* allocator() const { return allocator_; }
331
332  CodeGenState* state() { return state_; }
333  void set_state(CodeGenState* state) { state_ = state; }
334
335  void AddDeferred(DeferredCode* code) { deferred_.Add(code); }
336
337  bool in_spilled_code() const { return in_spilled_code_; }
338  void set_in_spilled_code(bool flag) { in_spilled_code_ = flag; }
339
340 private:
341  // Construction/Destruction
342  explicit CodeGenerator(MacroAssembler* masm);
343
344  // Accessors
345  inline bool is_eval();
346  Scope* scope();
347
348  // Generating deferred code.
349  void ProcessDeferred();
350
351  // State
352  ControlDestination* destination() const { return state_->destination(); }
353
354  // Track loop nesting level.
355  int loop_nesting() const { return loop_nesting_; }
356  void IncrementLoopNesting() { loop_nesting_++; }
357  void DecrementLoopNesting() { loop_nesting_--; }
358
359  // Node visitors.
360  void VisitStatements(ZoneList<Statement*>* statements);
361
362#define DEF_VISIT(type) \
363  void Visit##type(type* node);
364  AST_NODE_LIST(DEF_VISIT)
365#undef DEF_VISIT
366
367  // Visit a statement and then spill the virtual frame if control flow can
368  // reach the end of the statement (ie, it does not exit via break,
369  // continue, return, or throw).  This function is used temporarily while
370  // the code generator is being transformed.
371  void VisitAndSpill(Statement* statement);
372
373  // Visit a list of statements and then spill the virtual frame if control
374  // flow can reach the end of the list.
375  void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
376
377  // Main code generation function
378  void Generate(CompilationInfo* info);
379
380  // Generate the return sequence code.  Should be called no more than
381  // once per compiled function, immediately after binding the return
382  // target (which can not be done more than once).
383  void GenerateReturnSequence(Result* return_value);
384
385  // Returns the arguments allocation mode.
386  ArgumentsAllocationMode ArgumentsMode();
387
388  // Store the arguments object and allocate it if necessary.
389  Result StoreArgumentsObject(bool initial);
390
391  // The following are used by class Reference.
392  void LoadReference(Reference* ref);
393  void UnloadReference(Reference* ref);
394
395  static Operand ContextOperand(Register context, int index) {
396    return Operand(context, Context::SlotOffset(index));
397  }
398
399  Operand SlotOperand(Slot* slot, Register tmp);
400
401  Operand ContextSlotOperandCheckExtensions(Slot* slot,
402                                            Result tmp,
403                                            JumpTarget* slow);
404
405  // Expressions
406  static Operand GlobalObject() {
407    return ContextOperand(esi, Context::GLOBAL_INDEX);
408  }
409
410  void LoadCondition(Expression* x,
411                     ControlDestination* destination,
412                     bool force_control);
413  void Load(Expression* expr);
414  void LoadGlobal();
415  void LoadGlobalReceiver();
416
417  // Generate code to push the value of an expression on top of the frame
418  // and then spill the frame fully to memory.  This function is used
419  // temporarily while the code generator is being transformed.
420  void LoadAndSpill(Expression* expression);
421
422  // Read a value from a slot and leave it on top of the expression stack.
423  Result LoadFromSlot(Slot* slot, TypeofState typeof_state);
424  Result LoadFromSlotCheckForArguments(Slot* slot, TypeofState typeof_state);
425  Result LoadFromGlobalSlotCheckExtensions(Slot* slot,
426                                           TypeofState typeof_state,
427                                           JumpTarget* slow);
428
429  // Store the value on top of the expression stack into a slot, leaving the
430  // value in place.
431  void StoreToSlot(Slot* slot, InitState init_state);
432
433  // Support for compiling assignment expressions.
434  void EmitSlotAssignment(Assignment* node);
435  void EmitNamedPropertyAssignment(Assignment* node);
436  void EmitKeyedPropertyAssignment(Assignment* node);
437
438  // Receiver is passed on the frame and consumed.
439  Result EmitNamedLoad(Handle<String> name, bool is_contextual);
440
441  // If the store is contextual, value is passed on the frame and consumed.
442  // Otherwise, receiver and value are passed on the frame and consumed.
443  Result EmitNamedStore(Handle<String> name, bool is_contextual);
444
445  // Receiver and key are passed on the frame and consumed.
446  Result EmitKeyedLoad();
447
448  // Receiver, key, and value are passed on the frame and consumed.
449  Result EmitKeyedStore(StaticType* key_type);
450
451  // Special code for typeof expressions: Unfortunately, we must
452  // be careful when loading the expression in 'typeof'
453  // expressions. We are not allowed to throw reference errors for
454  // non-existing properties of the global object, so we must make it
455  // look like an explicit property access, instead of an access
456  // through the context chain.
457  void LoadTypeofExpression(Expression* x);
458
459  // Translate the value on top of the frame into control flow to the
460  // control destination.
461  void ToBoolean(ControlDestination* destination);
462
463  void GenericBinaryOperation(
464      Token::Value op,
465      StaticType* type,
466      OverwriteMode overwrite_mode);
467
468  // If possible, combine two constant smi values using op to produce
469  // a smi result, and push it on the virtual frame, all at compile time.
470  // Returns true if it succeeds.  Otherwise it has no effect.
471  bool FoldConstantSmis(Token::Value op, int left, int right);
472
473  // Emit code to perform a binary operation on a constant
474  // smi and a likely smi.  Consumes the Result *operand.
475  Result ConstantSmiBinaryOperation(Token::Value op,
476                                    Result* operand,
477                                    Handle<Object> constant_operand,
478                                    StaticType* type,
479                                    bool reversed,
480                                    OverwriteMode overwrite_mode);
481
482  // Emit code to perform a binary operation on two likely smis.
483  // The code to handle smi arguments is produced inline.
484  // Consumes the Results *left and *right.
485  Result LikelySmiBinaryOperation(Token::Value op,
486                                  Result* left,
487                                  Result* right,
488                                  OverwriteMode overwrite_mode);
489
490  void Comparison(AstNode* node,
491                  Condition cc,
492                  bool strict,
493                  ControlDestination* destination);
494
495  // To prevent long attacker-controlled byte sequences, integer constants
496  // from the JavaScript source are loaded in two parts if they are larger
497  // than 16 bits.
498  static const int kMaxSmiInlinedBits = 16;
499  bool IsUnsafeSmi(Handle<Object> value);
500  // Load an integer constant x into a register target or into the stack using
501  // at most 16 bits of user-controlled data per assembly operation.
502  void MoveUnsafeSmi(Register target, Handle<Object> value);
503  void StoreUnsafeSmiToLocal(int offset, Handle<Object> value);
504  void PushUnsafeSmi(Handle<Object> value);
505
506  void CallWithArguments(ZoneList<Expression*>* arguments,
507                         CallFunctionFlags flags,
508                         int position);
509
510  // An optimized implementation of expressions of the form
511  // x.apply(y, arguments).  We call x the applicand and y the receiver.
512  // The optimization avoids allocating an arguments object if possible.
513  void CallApplyLazy(Expression* applicand,
514                     Expression* receiver,
515                     VariableProxy* arguments,
516                     int position);
517
518  void CheckStack();
519
520  struct InlineRuntimeLUT {
521    void (CodeGenerator::*method)(ZoneList<Expression*>*);
522    const char* name;
523  };
524
525  static InlineRuntimeLUT* FindInlineRuntimeLUT(Handle<String> name);
526  bool CheckForInlineRuntimeCall(CallRuntime* node);
527  static bool PatchInlineRuntimeEntry(Handle<String> name,
528                                      const InlineRuntimeLUT& new_entry,
529                                      InlineRuntimeLUT* old_entry);
530
531  void ProcessDeclarations(ZoneList<Declaration*>* declarations);
532
533  static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
534
535  // Declare global variables and functions in the given array of
536  // name/value pairs.
537  void DeclareGlobals(Handle<FixedArray> pairs);
538
539  // Instantiate the function boilerplate.
540  Result InstantiateBoilerplate(Handle<JSFunction> boilerplate);
541
542  // Support for type checks.
543  void GenerateIsSmi(ZoneList<Expression*>* args);
544  void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
545  void GenerateIsArray(ZoneList<Expression*>* args);
546  void GenerateIsRegExp(ZoneList<Expression*>* args);
547  void GenerateIsObject(ZoneList<Expression*>* args);
548  void GenerateIsFunction(ZoneList<Expression*>* args);
549  void GenerateIsUndetectableObject(ZoneList<Expression*>* args);
550
551  // Support for construct call checks.
552  void GenerateIsConstructCall(ZoneList<Expression*>* args);
553
554  // Support for arguments.length and arguments[?].
555  void GenerateArgumentsLength(ZoneList<Expression*>* args);
556  void GenerateArgumentsAccess(ZoneList<Expression*>* args);
557
558  // Support for accessing the class and value fields of an object.
559  void GenerateClassOf(ZoneList<Expression*>* args);
560  void GenerateValueOf(ZoneList<Expression*>* args);
561  void GenerateSetValueOf(ZoneList<Expression*>* args);
562
563  // Fast support for charCodeAt(n).
564  void GenerateFastCharCodeAt(ZoneList<Expression*>* args);
565
566  // Fast support for object equality testing.
567  void GenerateObjectEquals(ZoneList<Expression*>* args);
568
569  void GenerateLog(ZoneList<Expression*>* args);
570
571  void GenerateGetFramePointer(ZoneList<Expression*>* args);
572
573  // Fast support for Math.random().
574  void GenerateRandomPositiveSmi(ZoneList<Expression*>* args);
575
576  // Fast support for StringAdd.
577  void GenerateStringAdd(ZoneList<Expression*>* args);
578
579  // Fast support for SubString.
580  void GenerateSubString(ZoneList<Expression*>* args);
581
582  // Fast support for StringCompare.
583  void GenerateStringCompare(ZoneList<Expression*>* args);
584
585  // Support for direct calls from JavaScript to native RegExp code.
586  void GenerateRegExpExec(ZoneList<Expression*>* args);
587
588  // Fast support for number to string.
589  void GenerateNumberToString(ZoneList<Expression*>* args);
590
591  // Fast call to transcendental functions.
592  void GenerateMathSin(ZoneList<Expression*>* args);
593  void GenerateMathCos(ZoneList<Expression*>* args);
594
595  // Simple condition analysis.
596  enum ConditionAnalysis {
597    ALWAYS_TRUE,
598    ALWAYS_FALSE,
599    DONT_KNOW
600  };
601  ConditionAnalysis AnalyzeCondition(Expression* cond);
602
603  // Methods used to indicate which source code is generated for. Source
604  // positions are collected by the assembler and emitted with the relocation
605  // information.
606  void CodeForFunctionPosition(FunctionLiteral* fun);
607  void CodeForReturnPosition(FunctionLiteral* fun);
608  void CodeForStatementPosition(Statement* stmt);
609  void CodeForDoWhileConditionPosition(DoWhileStatement* stmt);
610  void CodeForSourcePosition(int pos);
611
612#ifdef DEBUG
613  // True if the registers are valid for entry to a block.  There should
614  // be no frame-external references to (non-reserved) registers.
615  bool HasValidEntryRegisters();
616#endif
617
618  ZoneList<DeferredCode*> deferred_;
619
620  // Assembler
621  MacroAssembler* masm_;  // to generate code
622
623  CompilationInfo* info_;
624
625  // Code generation state
626  VirtualFrame* frame_;
627  RegisterAllocator* allocator_;
628  CodeGenState* state_;
629  int loop_nesting_;
630
631  // Jump targets.
632  // The target of the return from the function.
633  BreakTarget function_return_;
634
635  // True if the function return is shadowed (ie, jumping to the target
636  // function_return_ does not jump to the true function return, but rather
637  // to some unlinking code).
638  bool function_return_is_shadowed_;
639
640  // True when we are in code that expects the virtual frame to be fully
641  // spilled.  Some virtual frame function are disabled in DEBUG builds when
642  // called from spilled code, because they do not leave the virtual frame
643  // in a spilled state.
644  bool in_spilled_code_;
645
646  static InlineRuntimeLUT kInlineRuntimeLUT[];
647
648  friend class VirtualFrame;
649  friend class JumpTarget;
650  friend class Reference;
651  friend class Result;
652  friend class FastCodeGenerator;
653  friend class FullCodeGenerator;
654  friend class FullCodeGenSyntaxChecker;
655
656  friend class CodeGeneratorPatcher;  // Used in test-log-stack-tracer.cc
657
658  DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
659};
660
661
662// Compute a transcendental math function natively, or call the
663// TranscendentalCache runtime function.
664class TranscendentalCacheStub: public CodeStub {
665 public:
666  explicit TranscendentalCacheStub(TranscendentalCache::Type type)
667      : type_(type) {}
668  void Generate(MacroAssembler* masm);
669 private:
670  TranscendentalCache::Type type_;
671  Major MajorKey() { return TranscendentalCache; }
672  int MinorKey() { return type_; }
673  Runtime::FunctionId RuntimeFunction();
674  void GenerateOperation(MacroAssembler* masm);
675};
676
677
678// Flag that indicates how to generate code for the stub GenericBinaryOpStub.
679enum GenericBinaryFlags {
680  NO_GENERIC_BINARY_FLAGS = 0,
681  NO_SMI_CODE_IN_STUB = 1 << 0  // Omit smi code in stub.
682};
683
684
685class GenericBinaryOpStub: public CodeStub {
686 public:
687  GenericBinaryOpStub(Token::Value op,
688                      OverwriteMode mode,
689                      GenericBinaryFlags flags,
690                      NumberInfo::Type operands_type = NumberInfo::kUnknown)
691      : op_(op),
692        mode_(mode),
693        flags_(flags),
694        args_in_registers_(false),
695        args_reversed_(false),
696        name_(NULL),
697        operands_type_(operands_type) {
698    use_sse3_ = CpuFeatures::IsSupported(SSE3);
699    ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
700  }
701
702  // Generate code to call the stub with the supplied arguments. This will add
703  // code at the call site to prepare arguments either in registers or on the
704  // stack together with the actual call.
705  void GenerateCall(MacroAssembler* masm, Register left, Register right);
706  void GenerateCall(MacroAssembler* masm, Register left, Smi* right);
707  void GenerateCall(MacroAssembler* masm, Smi* left, Register right);
708
709  Result GenerateCall(MacroAssembler* masm,
710                      VirtualFrame* frame,
711                      Result* left,
712                      Result* right);
713
714 private:
715  Token::Value op_;
716  OverwriteMode mode_;
717  GenericBinaryFlags flags_;
718  bool args_in_registers_;  // Arguments passed in registers not on the stack.
719  bool args_reversed_;  // Left and right argument are swapped.
720  bool use_sse3_;
721  char* name_;
722  NumberInfo::Type operands_type_;  // Number type information of operands.
723
724  const char* GetName();
725
726#ifdef DEBUG
727  void Print() {
728    PrintF("GenericBinaryOpStub %d (op %s), "
729           "(mode %d, flags %d, registers %d, reversed %d, number_info %s)\n",
730           MinorKey(),
731           Token::String(op_),
732           static_cast<int>(mode_),
733           static_cast<int>(flags_),
734           static_cast<int>(args_in_registers_),
735           static_cast<int>(args_reversed_),
736           NumberInfo::ToString(operands_type_));
737  }
738#endif
739
740  // Minor key encoding in 16 bits NNNFRASOOOOOOOMM.
741  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
742  class OpBits: public BitField<Token::Value, 2, 7> {};
743  class SSE3Bits: public BitField<bool, 9, 1> {};
744  class ArgsInRegistersBits: public BitField<bool, 10, 1> {};
745  class ArgsReversedBits: public BitField<bool, 11, 1> {};
746  class FlagBits: public BitField<GenericBinaryFlags, 12, 1> {};
747  class NumberInfoBits: public BitField<NumberInfo::Type, 13, 3> {};
748
749  Major MajorKey() { return GenericBinaryOp; }
750  int MinorKey() {
751    // Encode the parameters in a unique 16 bit value.
752    return OpBits::encode(op_)
753           | ModeBits::encode(mode_)
754           | FlagBits::encode(flags_)
755           | SSE3Bits::encode(use_sse3_)
756           | ArgsInRegistersBits::encode(args_in_registers_)
757           | ArgsReversedBits::encode(args_reversed_)
758           | NumberInfoBits::encode(operands_type_);
759  }
760
761  void Generate(MacroAssembler* masm);
762  void GenerateSmiCode(MacroAssembler* masm, Label* slow);
763  void GenerateLoadArguments(MacroAssembler* masm);
764  void GenerateReturn(MacroAssembler* masm);
765  void GenerateHeapResultAllocation(MacroAssembler* masm, Label* alloc_failure);
766
767  bool ArgsInRegistersSupported() {
768    return op_ == Token::ADD || op_ == Token::SUB
769        || op_ == Token::MUL || op_ == Token::DIV;
770  }
771  bool IsOperationCommutative() {
772    return (op_ == Token::ADD) || (op_ == Token::MUL);
773  }
774
775  void SetArgsInRegisters() { args_in_registers_ = true; }
776  void SetArgsReversed() { args_reversed_ = true; }
777  bool HasSmiCodeInStub() { return (flags_ & NO_SMI_CODE_IN_STUB) == 0; }
778  bool HasArgsInRegisters() { return args_in_registers_; }
779  bool HasArgsReversed() { return args_reversed_; }
780};
781
782
783class StringStubBase: public CodeStub {
784 public:
785  // Generate code for copying characters using a simple loop. This should only
786  // be used in places where the number of characters is small and the
787  // additional setup and checking in GenerateCopyCharactersREP adds too much
788  // overhead. Copying of overlapping regions is not supported.
789  void GenerateCopyCharacters(MacroAssembler* masm,
790                              Register dest,
791                              Register src,
792                              Register count,
793                              Register scratch,
794                              bool ascii);
795
796  // Generate code for copying characters using the rep movs instruction.
797  // Copies ecx characters from esi to edi. Copying of overlapping regions is
798  // not supported.
799  void GenerateCopyCharactersREP(MacroAssembler* masm,
800                                 Register dest,     // Must be edi.
801                                 Register src,      // Must be esi.
802                                 Register count,    // Must be ecx.
803                                 Register scratch,  // Neither of the above.
804                                 bool ascii);
805
806  // Probe the symbol table for a two character string. If the string is
807  // not found by probing a jump to the label not_found is performed. This jump
808  // does not guarantee that the string is not in the symbol table. If the
809  // string is found the code falls through with the string in register eax.
810  void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
811                                            Register c1,
812                                            Register c2,
813                                            Register scratch1,
814                                            Register scratch2,
815                                            Register scratch3,
816                                            Label* not_found);
817
818  // Generate string hash.
819  void GenerateHashInit(MacroAssembler* masm,
820                        Register hash,
821                        Register character,
822                        Register scratch);
823  void GenerateHashAddCharacter(MacroAssembler* masm,
824                                Register hash,
825                                Register character,
826                                Register scratch);
827  void GenerateHashGetHash(MacroAssembler* masm,
828                           Register hash,
829                           Register scratch);
830};
831
832
833// Flag that indicates how to generate code for the stub StringAddStub.
834enum StringAddFlags {
835  NO_STRING_ADD_FLAGS = 0,
836  NO_STRING_CHECK_IN_STUB = 1 << 0  // Omit string check in stub.
837};
838
839
840class StringAddStub: public StringStubBase {
841 public:
842  explicit StringAddStub(StringAddFlags flags) {
843    string_check_ = ((flags & NO_STRING_CHECK_IN_STUB) == 0);
844  }
845
846 private:
847  Major MajorKey() { return StringAdd; }
848  int MinorKey() { return string_check_ ? 0 : 1; }
849
850  void Generate(MacroAssembler* masm);
851
852  // Should the stub check whether arguments are strings?
853  bool string_check_;
854};
855
856
857class SubStringStub: public StringStubBase {
858 public:
859  SubStringStub() {}
860
861 private:
862  Major MajorKey() { return SubString; }
863  int MinorKey() { return 0; }
864
865  void Generate(MacroAssembler* masm);
866};
867
868
869class StringCompareStub: public StringStubBase {
870 public:
871  explicit StringCompareStub() {
872  }
873
874  // Compare two flat ascii strings and returns result in eax after popping two
875  // arguments from the stack.
876  static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
877                                              Register left,
878                                              Register right,
879                                              Register scratch1,
880                                              Register scratch2,
881                                              Register scratch3);
882
883 private:
884  Major MajorKey() { return StringCompare; }
885  int MinorKey() { return 0; }
886
887  void Generate(MacroAssembler* masm);
888};
889
890
891class NumberToStringStub: public CodeStub {
892 public:
893  NumberToStringStub() { }
894
895  // Generate code to do a lookup in the number string cache. If the number in
896  // the register object is found in the cache the generated code falls through
897  // with the result in the result register. The object and the result register
898  // can be the same. If the number is not found in the cache the code jumps to
899  // the label not_found with only the content of register object unchanged.
900  static void GenerateLookupNumberStringCache(MacroAssembler* masm,
901                                              Register object,
902                                              Register result,
903                                              Register scratch1,
904                                              Register scratch2,
905                                              bool object_is_smi,
906                                              Label* not_found);
907
908 private:
909  Major MajorKey() { return NumberToString; }
910  int MinorKey() { return 0; }
911
912  void Generate(MacroAssembler* masm);
913
914  const char* GetName() { return "NumberToStringStub"; }
915
916#ifdef DEBUG
917  void Print() {
918    PrintF("NumberToStringStub\n");
919  }
920#endif
921};
922
923
924} }  // namespace v8::internal
925
926#endif  // V8_IA32_CODEGEN_IA32_H_
927