Home | History | Annotate | Download | only in ia32
      1 // Copyright 2012 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_MACRO_ASSEMBLER_IA32_H_
     29 #define V8_IA32_MACRO_ASSEMBLER_IA32_H_
     30 
     31 #include "assembler.h"
     32 #include "frames.h"
     33 #include "v8globals.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 // Convenience for platform-independent signatures.  We do not normally
     39 // distinguish memory operands from other operands on ia32.
     40 typedef Operand MemOperand;
     41 
     42 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
     43 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
     44 
     45 
     46 enum RegisterValueType {
     47   REGISTER_VALUE_IS_SMI,
     48   REGISTER_VALUE_IS_INT32
     49 };
     50 
     51 
     52 bool AreAliased(Register r1, Register r2, Register r3, Register r4);
     53 
     54 
     55 // MacroAssembler implements a collection of frequently used macros.
     56 class MacroAssembler: public Assembler {
     57  public:
     58   // The isolate parameter can be NULL if the macro assembler should
     59   // not use isolate-dependent functionality. In this case, it's the
     60   // responsibility of the caller to never invoke such function on the
     61   // macro assembler.
     62   MacroAssembler(Isolate* isolate, void* buffer, int size);
     63 
     64   void Load(Register dst, const Operand& src, Representation r);
     65   void Store(Register src, const Operand& dst, Representation r);
     66 
     67   // Operations on roots in the root-array.
     68   void LoadRoot(Register destination, Heap::RootListIndex index);
     69   void StoreRoot(Register source, Register scratch, Heap::RootListIndex index);
     70   void CompareRoot(Register with, Register scratch, Heap::RootListIndex index);
     71   // These methods can only be used with constant roots (i.e. non-writable
     72   // and not in new space).
     73   void CompareRoot(Register with, Heap::RootListIndex index);
     74   void CompareRoot(const Operand& with, Heap::RootListIndex index);
     75 
     76   // ---------------------------------------------------------------------------
     77   // GC Support
     78   enum RememberedSetFinalAction {
     79     kReturnAtEnd,
     80     kFallThroughAtEnd
     81   };
     82 
     83   // Record in the remembered set the fact that we have a pointer to new space
     84   // at the address pointed to by the addr register.  Only works if addr is not
     85   // in new space.
     86   void RememberedSetHelper(Register object,  // Used for debug code.
     87                            Register addr,
     88                            Register scratch,
     89                            SaveFPRegsMode save_fp,
     90                            RememberedSetFinalAction and_then);
     91 
     92   void CheckPageFlag(Register object,
     93                      Register scratch,
     94                      int mask,
     95                      Condition cc,
     96                      Label* condition_met,
     97                      Label::Distance condition_met_distance = Label::kFar);
     98 
     99   void CheckPageFlagForMap(
    100       Handle<Map> map,
    101       int mask,
    102       Condition cc,
    103       Label* condition_met,
    104       Label::Distance condition_met_distance = Label::kFar);
    105 
    106   void CheckMapDeprecated(Handle<Map> map,
    107                           Register scratch,
    108                           Label* if_deprecated);
    109 
    110   // Check if object is in new space.  Jumps if the object is not in new space.
    111   // The register scratch can be object itself, but scratch will be clobbered.
    112   void JumpIfNotInNewSpace(Register object,
    113                            Register scratch,
    114                            Label* branch,
    115                            Label::Distance distance = Label::kFar) {
    116     InNewSpace(object, scratch, zero, branch, distance);
    117   }
    118 
    119   // Check if object is in new space.  Jumps if the object is in new space.
    120   // The register scratch can be object itself, but it will be clobbered.
    121   void JumpIfInNewSpace(Register object,
    122                         Register scratch,
    123                         Label* branch,
    124                         Label::Distance distance = Label::kFar) {
    125     InNewSpace(object, scratch, not_zero, branch, distance);
    126   }
    127 
    128   // Check if an object has a given incremental marking color.  Also uses ecx!
    129   void HasColor(Register object,
    130                 Register scratch0,
    131                 Register scratch1,
    132                 Label* has_color,
    133                 Label::Distance has_color_distance,
    134                 int first_bit,
    135                 int second_bit);
    136 
    137   void JumpIfBlack(Register object,
    138                    Register scratch0,
    139                    Register scratch1,
    140                    Label* on_black,
    141                    Label::Distance on_black_distance = Label::kFar);
    142 
    143   // Checks the color of an object.  If the object is already grey or black
    144   // then we just fall through, since it is already live.  If it is white and
    145   // we can determine that it doesn't need to be scanned, then we just mark it
    146   // black and fall through.  For the rest we jump to the label so the
    147   // incremental marker can fix its assumptions.
    148   void EnsureNotWhite(Register object,
    149                       Register scratch1,
    150                       Register scratch2,
    151                       Label* object_is_white_and_not_data,
    152                       Label::Distance distance);
    153 
    154   // Notify the garbage collector that we wrote a pointer into an object.
    155   // |object| is the object being stored into, |value| is the object being
    156   // stored.  value and scratch registers are clobbered by the operation.
    157   // The offset is the offset from the start of the object, not the offset from
    158   // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
    159   void RecordWriteField(
    160       Register object,
    161       int offset,
    162       Register value,
    163       Register scratch,
    164       SaveFPRegsMode save_fp,
    165       RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
    166       SmiCheck smi_check = INLINE_SMI_CHECK);
    167 
    168   // As above, but the offset has the tag presubtracted.  For use with
    169   // Operand(reg, off).
    170   void RecordWriteContextSlot(
    171       Register context,
    172       int offset,
    173       Register value,
    174       Register scratch,
    175       SaveFPRegsMode save_fp,
    176       RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
    177       SmiCheck smi_check = INLINE_SMI_CHECK) {
    178     RecordWriteField(context,
    179                      offset + kHeapObjectTag,
    180                      value,
    181                      scratch,
    182                      save_fp,
    183                      remembered_set_action,
    184                      smi_check);
    185   }
    186 
    187   // Notify the garbage collector that we wrote a pointer into a fixed array.
    188   // |array| is the array being stored into, |value| is the
    189   // object being stored.  |index| is the array index represented as a
    190   // Smi. All registers are clobbered by the operation RecordWriteArray
    191   // filters out smis so it does not update the write barrier if the
    192   // value is a smi.
    193   void RecordWriteArray(
    194       Register array,
    195       Register value,
    196       Register index,
    197       SaveFPRegsMode save_fp,
    198       RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
    199       SmiCheck smi_check = INLINE_SMI_CHECK);
    200 
    201   // For page containing |object| mark region covering |address|
    202   // dirty. |object| is the object being stored into, |value| is the
    203   // object being stored. The address and value registers are clobbered by the
    204   // operation. RecordWrite filters out smis so it does not update the
    205   // write barrier if the value is a smi.
    206   void RecordWrite(
    207       Register object,
    208       Register address,
    209       Register value,
    210       SaveFPRegsMode save_fp,
    211       RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
    212       SmiCheck smi_check = INLINE_SMI_CHECK);
    213 
    214   // For page containing |object| mark the region covering the object's map
    215   // dirty. |object| is the object being stored into, |map| is the Map object
    216   // that was stored.
    217   void RecordWriteForMap(
    218       Register object,
    219       Handle<Map> map,
    220       Register scratch1,
    221       Register scratch2,
    222       SaveFPRegsMode save_fp);
    223 
    224 #ifdef ENABLE_DEBUGGER_SUPPORT
    225   // ---------------------------------------------------------------------------
    226   // Debugger Support
    227 
    228   void DebugBreak();
    229 #endif
    230 
    231   // Generates function and stub prologue code.
    232   void Prologue(PrologueFrameMode frame_mode);
    233 
    234   // Enter specific kind of exit frame. Expects the number of
    235   // arguments in register eax and sets up the number of arguments in
    236   // register edi and the pointer to the first argument in register
    237   // esi.
    238   void EnterExitFrame(bool save_doubles);
    239 
    240   void EnterApiExitFrame(int argc);
    241 
    242   // Leave the current exit frame. Expects the return value in
    243   // register eax:edx (untouched) and the pointer to the first
    244   // argument in register esi.
    245   void LeaveExitFrame(bool save_doubles);
    246 
    247   // Leave the current exit frame. Expects the return value in
    248   // register eax (untouched).
    249   void LeaveApiExitFrame(bool restore_context);
    250 
    251   // Find the function context up the context chain.
    252   void LoadContext(Register dst, int context_chain_length);
    253 
    254   // Conditionally load the cached Array transitioned map of type
    255   // transitioned_kind from the native context if the map in register
    256   // map_in_out is the cached Array map in the native context of
    257   // expected_kind.
    258   void LoadTransitionedArrayMapConditional(
    259       ElementsKind expected_kind,
    260       ElementsKind transitioned_kind,
    261       Register map_in_out,
    262       Register scratch,
    263       Label* no_map_match);
    264 
    265   // Load the initial map for new Arrays from a JSFunction.
    266   void LoadInitialArrayMap(Register function_in,
    267                            Register scratch,
    268                            Register map_out,
    269                            bool can_have_holes);
    270 
    271   void LoadGlobalContext(Register global_context);
    272 
    273   // Load the global function with the given index.
    274   void LoadGlobalFunction(int index, Register function);
    275 
    276   // Load the initial map from the global function. The registers
    277   // function and map can be the same.
    278   void LoadGlobalFunctionInitialMap(Register function, Register map);
    279 
    280   // Push and pop the registers that can hold pointers.
    281   void PushSafepointRegisters() { pushad(); }
    282   void PopSafepointRegisters() { popad(); }
    283   // Store the value in register/immediate src in the safepoint
    284   // register stack slot for register dst.
    285   void StoreToSafepointRegisterSlot(Register dst, Register src);
    286   void StoreToSafepointRegisterSlot(Register dst, Immediate src);
    287   void LoadFromSafepointRegisterSlot(Register dst, Register src);
    288 
    289   void LoadHeapObject(Register result, Handle<HeapObject> object);
    290   void CmpHeapObject(Register reg, Handle<HeapObject> object);
    291   void PushHeapObject(Handle<HeapObject> object);
    292 
    293   void LoadObject(Register result, Handle<Object> object) {
    294     AllowDeferredHandleDereference heap_object_check;
    295     if (object->IsHeapObject()) {
    296       LoadHeapObject(result, Handle<HeapObject>::cast(object));
    297     } else {
    298       Set(result, Immediate(object));
    299     }
    300   }
    301 
    302   void CmpObject(Register reg, Handle<Object> object) {
    303     AllowDeferredHandleDereference heap_object_check;
    304     if (object->IsHeapObject()) {
    305       CmpHeapObject(reg, Handle<HeapObject>::cast(object));
    306     } else {
    307       cmp(reg, Immediate(object));
    308     }
    309   }
    310 
    311   // ---------------------------------------------------------------------------
    312   // JavaScript invokes
    313 
    314   // Set up call kind marking in ecx. The method takes ecx as an
    315   // explicit first parameter to make the code more readable at the
    316   // call sites.
    317   void SetCallKind(Register dst, CallKind kind);
    318 
    319   // Invoke the JavaScript function code by either calling or jumping.
    320   void InvokeCode(Register code,
    321                   const ParameterCount& expected,
    322                   const ParameterCount& actual,
    323                   InvokeFlag flag,
    324                   const CallWrapper& call_wrapper,
    325                   CallKind call_kind) {
    326     InvokeCode(Operand(code), expected, actual, flag, call_wrapper, call_kind);
    327   }
    328 
    329   void InvokeCode(const Operand& code,
    330                   const ParameterCount& expected,
    331                   const ParameterCount& actual,
    332                   InvokeFlag flag,
    333                   const CallWrapper& call_wrapper,
    334                   CallKind call_kind);
    335 
    336   void InvokeCode(Handle<Code> code,
    337                   const ParameterCount& expected,
    338                   const ParameterCount& actual,
    339                   RelocInfo::Mode rmode,
    340                   InvokeFlag flag,
    341                   const CallWrapper& call_wrapper,
    342                   CallKind call_kind);
    343 
    344   // Invoke the JavaScript function in the given register. Changes the
    345   // current context to the context in the function before invoking.
    346   void InvokeFunction(Register function,
    347                       const ParameterCount& actual,
    348                       InvokeFlag flag,
    349                       const CallWrapper& call_wrapper,
    350                       CallKind call_kind);
    351 
    352   void InvokeFunction(Register function,
    353                       const ParameterCount& expected,
    354                       const ParameterCount& actual,
    355                       InvokeFlag flag,
    356                       const CallWrapper& call_wrapper,
    357                       CallKind call_kind);
    358 
    359   void InvokeFunction(Handle<JSFunction> function,
    360                       const ParameterCount& expected,
    361                       const ParameterCount& actual,
    362                       InvokeFlag flag,
    363                       const CallWrapper& call_wrapper,
    364                       CallKind call_kind);
    365 
    366   // Invoke specified builtin JavaScript function. Adds an entry to
    367   // the unresolved list if the name does not resolve.
    368   void InvokeBuiltin(Builtins::JavaScript id,
    369                      InvokeFlag flag,
    370                      const CallWrapper& call_wrapper = NullCallWrapper());
    371 
    372   // Store the function for the given builtin in the target register.
    373   void GetBuiltinFunction(Register target, Builtins::JavaScript id);
    374 
    375   // Store the code object for the given builtin in the target register.
    376   void GetBuiltinEntry(Register target, Builtins::JavaScript id);
    377 
    378   // Expression support
    379   void Set(Register dst, const Immediate& x);
    380   void Set(const Operand& dst, const Immediate& x);
    381 
    382   // cvtsi2sd instruction only writes to the low 64-bit of dst register, which
    383   // hinders register renaming and makes dependence chains longer. So we use
    384   // xorps to clear the dst register before cvtsi2sd to solve this issue.
    385   void Cvtsi2sd(XMMRegister dst, Register src) { Cvtsi2sd(dst, Operand(src)); }
    386   void Cvtsi2sd(XMMRegister dst, const Operand& src);
    387 
    388   // Support for constant splitting.
    389   bool IsUnsafeImmediate(const Immediate& x);
    390   void SafeSet(Register dst, const Immediate& x);
    391   void SafePush(const Immediate& x);
    392 
    393   // Compare object type for heap object.
    394   // Incoming register is heap_object and outgoing register is map.
    395   void CmpObjectType(Register heap_object, InstanceType type, Register map);
    396 
    397   // Compare instance type for map.
    398   void CmpInstanceType(Register map, InstanceType type);
    399 
    400   // Check if a map for a JSObject indicates that the object has fast elements.
    401   // Jump to the specified label if it does not.
    402   void CheckFastElements(Register map,
    403                          Label* fail,
    404                          Label::Distance distance = Label::kFar);
    405 
    406   // Check if a map for a JSObject indicates that the object can have both smi
    407   // and HeapObject elements.  Jump to the specified label if it does not.
    408   void CheckFastObjectElements(Register map,
    409                                Label* fail,
    410                                Label::Distance distance = Label::kFar);
    411 
    412   // Check if a map for a JSObject indicates that the object has fast smi only
    413   // elements.  Jump to the specified label if it does not.
    414   void CheckFastSmiElements(Register map,
    415                             Label* fail,
    416                             Label::Distance distance = Label::kFar);
    417 
    418   // Check to see if maybe_number can be stored as a double in
    419   // FastDoubleElements. If it can, store it at the index specified by key in
    420   // the FastDoubleElements array elements, otherwise jump to fail.
    421   void StoreNumberToDoubleElements(Register maybe_number,
    422                                    Register elements,
    423                                    Register key,
    424                                    Register scratch1,
    425                                    XMMRegister scratch2,
    426                                    Label* fail,
    427                                    bool specialize_for_processor,
    428                                    int offset = 0);
    429 
    430   // Compare an object's map with the specified map.
    431   void CompareMap(Register obj, Handle<Map> map);
    432 
    433   // Check if the map of an object is equal to a specified map and branch to
    434   // label if not. Skip the smi check if not required (object is known to be a
    435   // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
    436   // against maps that are ElementsKind transition maps of the specified map.
    437   void CheckMap(Register obj,
    438                 Handle<Map> map,
    439                 Label* fail,
    440                 SmiCheckType smi_check_type);
    441 
    442   // Check if the map of an object is equal to a specified map and branch to a
    443   // specified target if equal. Skip the smi check if not required (object is
    444   // known to be a heap object)
    445   void DispatchMap(Register obj,
    446                    Register unused,
    447                    Handle<Map> map,
    448                    Handle<Code> success,
    449                    SmiCheckType smi_check_type);
    450 
    451   // Check if the object in register heap_object is a string. Afterwards the
    452   // register map contains the object map and the register instance_type
    453   // contains the instance_type. The registers map and instance_type can be the
    454   // same in which case it contains the instance type afterwards. Either of the
    455   // registers map and instance_type can be the same as heap_object.
    456   Condition IsObjectStringType(Register heap_object,
    457                                Register map,
    458                                Register instance_type);
    459 
    460   // Check if the object in register heap_object is a name. Afterwards the
    461   // register map contains the object map and the register instance_type
    462   // contains the instance_type. The registers map and instance_type can be the
    463   // same in which case it contains the instance type afterwards. Either of the
    464   // registers map and instance_type can be the same as heap_object.
    465   Condition IsObjectNameType(Register heap_object,
    466                              Register map,
    467                              Register instance_type);
    468 
    469   // Check if a heap object's type is in the JSObject range, not including
    470   // JSFunction.  The object's map will be loaded in the map register.
    471   // Any or all of the three registers may be the same.
    472   // The contents of the scratch register will always be overwritten.
    473   void IsObjectJSObjectType(Register heap_object,
    474                             Register map,
    475                             Register scratch,
    476                             Label* fail);
    477 
    478   // The contents of the scratch register will be overwritten.
    479   void IsInstanceJSObjectType(Register map, Register scratch, Label* fail);
    480 
    481   // FCmp is similar to integer cmp, but requires unsigned
    482   // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
    483   void FCmp();
    484 
    485   void ClampUint8(Register reg);
    486 
    487   void ClampDoubleToUint8(XMMRegister input_reg,
    488                           XMMRegister scratch_reg,
    489                           Register result_reg);
    490 
    491   void SlowTruncateToI(Register result_reg, Register input_reg,
    492       int offset = HeapNumber::kValueOffset - kHeapObjectTag);
    493 
    494   void TruncateHeapNumberToI(Register result_reg, Register input_reg);
    495   void TruncateDoubleToI(Register result_reg, XMMRegister input_reg);
    496   void TruncateX87TOSToI(Register result_reg);
    497 
    498   void DoubleToI(Register result_reg, XMMRegister input_reg,
    499       XMMRegister scratch, MinusZeroMode minus_zero_mode,
    500       Label* conversion_failed, Label::Distance dst = Label::kFar);
    501   void X87TOSToI(Register result_reg, MinusZeroMode minus_zero_mode,
    502       Label* conversion_failed, Label::Distance dst = Label::kFar);
    503 
    504   void TaggedToI(Register result_reg, Register input_reg, XMMRegister temp,
    505       MinusZeroMode minus_zero_mode, Label* lost_precision);
    506 
    507   // Smi tagging support.
    508   void SmiTag(Register reg) {
    509     STATIC_ASSERT(kSmiTag == 0);
    510     STATIC_ASSERT(kSmiTagSize == 1);
    511     add(reg, reg);
    512   }
    513   void SmiUntag(Register reg) {
    514     sar(reg, kSmiTagSize);
    515   }
    516 
    517   // Modifies the register even if it does not contain a Smi!
    518   void SmiUntag(Register reg, Label* is_smi) {
    519     STATIC_ASSERT(kSmiTagSize == 1);
    520     sar(reg, kSmiTagSize);
    521     STATIC_ASSERT(kSmiTag == 0);
    522     j(not_carry, is_smi);
    523   }
    524 
    525   void LoadUint32(XMMRegister dst, Register src, XMMRegister scratch);
    526   void LoadUint32NoSSE2(Register src);
    527 
    528   // Jump the register contains a smi.
    529   inline void JumpIfSmi(Register value,
    530                         Label* smi_label,
    531                         Label::Distance distance = Label::kFar) {
    532     test(value, Immediate(kSmiTagMask));
    533     j(zero, smi_label, distance);
    534   }
    535   // Jump if the operand is a smi.
    536   inline void JumpIfSmi(Operand value,
    537                         Label* smi_label,
    538                         Label::Distance distance = Label::kFar) {
    539     test(value, Immediate(kSmiTagMask));
    540     j(zero, smi_label, distance);
    541   }
    542   // Jump if register contain a non-smi.
    543   inline void JumpIfNotSmi(Register value,
    544                            Label* not_smi_label,
    545                            Label::Distance distance = Label::kFar) {
    546     test(value, Immediate(kSmiTagMask));
    547     j(not_zero, not_smi_label, distance);
    548   }
    549 
    550   void LoadInstanceDescriptors(Register map, Register descriptors);
    551   void EnumLength(Register dst, Register map);
    552   void NumberOfOwnDescriptors(Register dst, Register map);
    553 
    554   template<typename Field>
    555   void DecodeField(Register reg) {
    556     static const int shift = Field::kShift;
    557     static const int mask = (Field::kMask >> Field::kShift) << kSmiTagSize;
    558     sar(reg, shift);
    559     and_(reg, Immediate(mask));
    560   }
    561   void LoadPowerOf2(XMMRegister dst, Register scratch, int power);
    562 
    563   // Abort execution if argument is not a number, enabled via --debug-code.
    564   void AssertNumber(Register object);
    565 
    566   // Abort execution if argument is not a smi, enabled via --debug-code.
    567   void AssertSmi(Register object);
    568 
    569   // Abort execution if argument is a smi, enabled via --debug-code.
    570   void AssertNotSmi(Register object);
    571 
    572   // Abort execution if argument is not a string, enabled via --debug-code.
    573   void AssertString(Register object);
    574 
    575   // Abort execution if argument is not a name, enabled via --debug-code.
    576   void AssertName(Register object);
    577 
    578   // ---------------------------------------------------------------------------
    579   // Exception handling
    580 
    581   // Push a new try handler and link it into try handler chain.
    582   void PushTryHandler(StackHandler::Kind kind, int handler_index);
    583 
    584   // Unlink the stack handler on top of the stack from the try handler chain.
    585   void PopTryHandler();
    586 
    587   // Throw to the top handler in the try hander chain.
    588   void Throw(Register value);
    589 
    590   // Throw past all JS frames to the top JS entry frame.
    591   void ThrowUncatchable(Register value);
    592 
    593   // Throw a message string as an exception.
    594   void Throw(BailoutReason reason);
    595 
    596   // Throw a message string as an exception if a condition is not true.
    597   void ThrowIf(Condition cc, BailoutReason reason);
    598 
    599   // ---------------------------------------------------------------------------
    600   // Inline caching support
    601 
    602   // Generate code for checking access rights - used for security checks
    603   // on access to global objects across environments. The holder register
    604   // is left untouched, but the scratch register is clobbered.
    605   void CheckAccessGlobalProxy(Register holder_reg,
    606                               Register scratch1,
    607                               Register scratch2,
    608                               Label* miss);
    609 
    610   void GetNumberHash(Register r0, Register scratch);
    611 
    612   void LoadFromNumberDictionary(Label* miss,
    613                                 Register elements,
    614                                 Register key,
    615                                 Register r0,
    616                                 Register r1,
    617                                 Register r2,
    618                                 Register result);
    619 
    620 
    621   // ---------------------------------------------------------------------------
    622   // Allocation support
    623 
    624   // Allocate an object in new space or old pointer space. If the given space
    625   // is exhausted control continues at the gc_required label. The allocated
    626   // object is returned in result and end of the new object is returned in
    627   // result_end. The register scratch can be passed as no_reg in which case
    628   // an additional object reference will be added to the reloc info. The
    629   // returned pointers in result and result_end have not yet been tagged as
    630   // heap objects. If result_contains_top_on_entry is true the content of
    631   // result is known to be the allocation top on entry (could be result_end
    632   // from a previous call). If result_contains_top_on_entry is true scratch
    633   // should be no_reg as it is never used.
    634   void Allocate(int object_size,
    635                 Register result,
    636                 Register result_end,
    637                 Register scratch,
    638                 Label* gc_required,
    639                 AllocationFlags flags);
    640 
    641   void Allocate(int header_size,
    642                 ScaleFactor element_size,
    643                 Register element_count,
    644                 RegisterValueType element_count_type,
    645                 Register result,
    646                 Register result_end,
    647                 Register scratch,
    648                 Label* gc_required,
    649                 AllocationFlags flags);
    650 
    651   void Allocate(Register object_size,
    652                 Register result,
    653                 Register result_end,
    654                 Register scratch,
    655                 Label* gc_required,
    656                 AllocationFlags flags);
    657 
    658   // Undo allocation in new space. The object passed and objects allocated after
    659   // it will no longer be allocated. Make sure that no pointers are left to the
    660   // object(s) no longer allocated as they would be invalid when allocation is
    661   // un-done.
    662   void UndoAllocationInNewSpace(Register object);
    663 
    664   // Allocate a heap number in new space with undefined value. The
    665   // register scratch2 can be passed as no_reg; the others must be
    666   // valid registers. Returns tagged pointer in result register, or
    667   // jumps to gc_required if new space is full.
    668   void AllocateHeapNumber(Register result,
    669                           Register scratch1,
    670                           Register scratch2,
    671                           Label* gc_required);
    672 
    673   // Allocate a sequential string. All the header fields of the string object
    674   // are initialized.
    675   void AllocateTwoByteString(Register result,
    676                              Register length,
    677                              Register scratch1,
    678                              Register scratch2,
    679                              Register scratch3,
    680                              Label* gc_required);
    681   void AllocateAsciiString(Register result,
    682                            Register length,
    683                            Register scratch1,
    684                            Register scratch2,
    685                            Register scratch3,
    686                            Label* gc_required);
    687   void AllocateAsciiString(Register result,
    688                            int length,
    689                            Register scratch1,
    690                            Register scratch2,
    691                            Label* gc_required);
    692 
    693   // Allocate a raw cons string object. Only the map field of the result is
    694   // initialized.
    695   void AllocateTwoByteConsString(Register result,
    696                           Register scratch1,
    697                           Register scratch2,
    698                           Label* gc_required);
    699   void AllocateAsciiConsString(Register result,
    700                                Register scratch1,
    701                                Register scratch2,
    702                                Label* gc_required);
    703 
    704   // Allocate a raw sliced string object. Only the map field of the result is
    705   // initialized.
    706   void AllocateTwoByteSlicedString(Register result,
    707                             Register scratch1,
    708                             Register scratch2,
    709                             Label* gc_required);
    710   void AllocateAsciiSlicedString(Register result,
    711                                  Register scratch1,
    712                                  Register scratch2,
    713                                  Label* gc_required);
    714 
    715   // Copy memory, byte-by-byte, from source to destination.  Not optimized for
    716   // long or aligned copies.
    717   // The contents of index and scratch are destroyed.
    718   void CopyBytes(Register source,
    719                  Register destination,
    720                  Register length,
    721                  Register scratch);
    722 
    723   // Initialize fields with filler values.  Fields starting at |start_offset|
    724   // not including end_offset are overwritten with the value in |filler|.  At
    725   // the end the loop, |start_offset| takes the value of |end_offset|.
    726   void InitializeFieldsWithFiller(Register start_offset,
    727                                   Register end_offset,
    728                                   Register filler);
    729 
    730   // ---------------------------------------------------------------------------
    731   // Support functions.
    732 
    733   // Check a boolean-bit of a Smi field.
    734   void BooleanBitTest(Register object, int field_offset, int bit_index);
    735 
    736   // Check if result is zero and op is negative.
    737   void NegativeZeroTest(Register result, Register op, Label* then_label);
    738 
    739   // Check if result is zero and any of op1 and op2 are negative.
    740   // Register scratch is destroyed, and it must be different from op2.
    741   void NegativeZeroTest(Register result, Register op1, Register op2,
    742                         Register scratch, Label* then_label);
    743 
    744   // Try to get function prototype of a function and puts the value in
    745   // the result register. Checks that the function really is a
    746   // function and jumps to the miss label if the fast checks fail. The
    747   // function register will be untouched; the other registers may be
    748   // clobbered.
    749   void TryGetFunctionPrototype(Register function,
    750                                Register result,
    751                                Register scratch,
    752                                Label* miss,
    753                                bool miss_on_bound_function = false);
    754 
    755   // Generates code for reporting that an illegal operation has
    756   // occurred.
    757   void IllegalOperation(int num_arguments);
    758 
    759   // Picks out an array index from the hash field.
    760   // Register use:
    761   //   hash - holds the index's hash. Clobbered.
    762   //   index - holds the overwritten index on exit.
    763   void IndexFromHash(Register hash, Register index);
    764 
    765   // ---------------------------------------------------------------------------
    766   // Runtime calls
    767 
    768   // Call a code stub.  Generate the code if necessary.
    769   void CallStub(CodeStub* stub, TypeFeedbackId ast_id = TypeFeedbackId::None());
    770 
    771   // Tail call a code stub (jump).  Generate the code if necessary.
    772   void TailCallStub(CodeStub* stub);
    773 
    774   // Return from a code stub after popping its arguments.
    775   void StubReturn(int argc);
    776 
    777   // Call a runtime routine.
    778   void CallRuntime(const Runtime::Function* f,
    779                    int num_arguments,
    780                    SaveFPRegsMode save_doubles = kDontSaveFPRegs);
    781   void CallRuntimeSaveDoubles(Runtime::FunctionId id) {
    782     const Runtime::Function* function = Runtime::FunctionForId(id);
    783     CallRuntime(function, function->nargs, kSaveFPRegs);
    784   }
    785 
    786   // Convenience function: Same as above, but takes the fid instead.
    787   void CallRuntime(Runtime::FunctionId id,
    788                    int num_arguments,
    789                    SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
    790     CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles);
    791   }
    792 
    793   // Convenience function: call an external reference.
    794   void CallExternalReference(ExternalReference ref, int num_arguments);
    795 
    796   // Tail call of a runtime routine (jump).
    797   // Like JumpToExternalReference, but also takes care of passing the number
    798   // of parameters.
    799   void TailCallExternalReference(const ExternalReference& ext,
    800                                  int num_arguments,
    801                                  int result_size);
    802 
    803   // Convenience function: tail call a runtime routine (jump).
    804   void TailCallRuntime(Runtime::FunctionId fid,
    805                        int num_arguments,
    806                        int result_size);
    807 
    808   // Before calling a C-function from generated code, align arguments on stack.
    809   // After aligning the frame, arguments must be stored in esp[0], esp[4],
    810   // etc., not pushed. The argument count assumes all arguments are word sized.
    811   // Some compilers/platforms require the stack to be aligned when calling
    812   // C++ code.
    813   // Needs a scratch register to do some arithmetic. This register will be
    814   // trashed.
    815   void PrepareCallCFunction(int num_arguments, Register scratch);
    816 
    817   // Calls a C function and cleans up the space for arguments allocated
    818   // by PrepareCallCFunction. The called function is not allowed to trigger a
    819   // garbage collection, since that might move the code and invalidate the
    820   // return address (unless this is somehow accounted for by the called
    821   // function).
    822   void CallCFunction(ExternalReference function, int num_arguments);
    823   void CallCFunction(Register function, int num_arguments);
    824 
    825   // Prepares stack to put arguments (aligns and so on). Reserves
    826   // space for return value if needed (assumes the return value is a handle).
    827   // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1)
    828   // etc. Saves context (esi). If space was reserved for return value then
    829   // stores the pointer to the reserved slot into esi.
    830   void PrepareCallApiFunction(int argc);
    831 
    832   // Calls an API function.  Allocates HandleScope, extracts returned value
    833   // from handle and propagates exceptions.  Clobbers ebx, edi and
    834   // caller-save registers.  Restores context.  On return removes
    835   // stack_space * kPointerSize (GCed).
    836   void CallApiFunctionAndReturn(Address function_address,
    837                                 Address thunk_address,
    838                                 Operand thunk_last_arg,
    839                                 int stack_space,
    840                                 Operand return_value_operand,
    841                                 Operand* context_restore_operand);
    842 
    843   // Jump to a runtime routine.
    844   void JumpToExternalReference(const ExternalReference& ext);
    845 
    846   // ---------------------------------------------------------------------------
    847   // Utilities
    848 
    849   void Ret();
    850 
    851   // Return and drop arguments from stack, where the number of arguments
    852   // may be bigger than 2^16 - 1.  Requires a scratch register.
    853   void Ret(int bytes_dropped, Register scratch);
    854 
    855   // Emit code to discard a non-negative number of pointer-sized elements
    856   // from the stack, clobbering only the esp register.
    857   void Drop(int element_count);
    858 
    859   void Call(Label* target) { call(target); }
    860   void Push(Register src) { push(src); }
    861   void Pop(Register dst) { pop(dst); }
    862 
    863   // Emit call to the code we are currently generating.
    864   void CallSelf() {
    865     Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
    866     call(self, RelocInfo::CODE_TARGET);
    867   }
    868 
    869   // Move if the registers are not identical.
    870   void Move(Register target, Register source);
    871 
    872   // Push a handle value.
    873   void Push(Handle<Object> handle) { push(Immediate(handle)); }
    874   void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
    875 
    876   Handle<Object> CodeObject() {
    877     ASSERT(!code_object_.is_null());
    878     return code_object_;
    879   }
    880 
    881   // Insert code to verify that the x87 stack has the specified depth (0-7)
    882   void VerifyX87StackDepth(uint32_t depth);
    883 
    884   // ---------------------------------------------------------------------------
    885   // StatsCounter support
    886 
    887   void SetCounter(StatsCounter* counter, int value);
    888   void IncrementCounter(StatsCounter* counter, int value);
    889   void DecrementCounter(StatsCounter* counter, int value);
    890   void IncrementCounter(Condition cc, StatsCounter* counter, int value);
    891   void DecrementCounter(Condition cc, StatsCounter* counter, int value);
    892 
    893 
    894   // ---------------------------------------------------------------------------
    895   // Debugging
    896 
    897   // Calls Abort(msg) if the condition cc is not satisfied.
    898   // Use --debug_code to enable.
    899   void Assert(Condition cc, BailoutReason reason);
    900 
    901   void AssertFastElements(Register elements);
    902 
    903   // Like Assert(), but always enabled.
    904   void Check(Condition cc, BailoutReason reason);
    905 
    906   // Print a message to stdout and abort execution.
    907   void Abort(BailoutReason reason);
    908 
    909   // Check that the stack is aligned.
    910   void CheckStackAlignment();
    911 
    912   // Verify restrictions about code generated in stubs.
    913   void set_generating_stub(bool value) { generating_stub_ = value; }
    914   bool generating_stub() { return generating_stub_; }
    915   void set_has_frame(bool value) { has_frame_ = value; }
    916   bool has_frame() { return has_frame_; }
    917   inline bool AllowThisStubCall(CodeStub* stub);
    918 
    919   // ---------------------------------------------------------------------------
    920   // String utilities.
    921 
    922   // Generate code to do a lookup in the number string cache. If the number in
    923   // the register object is found in the cache the generated code falls through
    924   // with the result in the result register. The object and the result register
    925   // can be the same. If the number is not found in the cache the code jumps to
    926   // the label not_found with only the content of register object unchanged.
    927   void LookupNumberStringCache(Register object,
    928                                Register result,
    929                                Register scratch1,
    930                                Register scratch2,
    931                                Label* not_found);
    932 
    933   // Check whether the instance type represents a flat ASCII string. Jump to the
    934   // label if not. If the instance type can be scratched specify same register
    935   // for both instance type and scratch.
    936   void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type,
    937                                               Register scratch,
    938                                               Label* on_not_flat_ascii_string);
    939 
    940   // Checks if both objects are sequential ASCII strings, and jumps to label
    941   // if either is not.
    942   void JumpIfNotBothSequentialAsciiStrings(Register object1,
    943                                            Register object2,
    944                                            Register scratch1,
    945                                            Register scratch2,
    946                                            Label* on_not_flat_ascii_strings);
    947 
    948   // Checks if the given register or operand is a unique name
    949   void JumpIfNotUniqueName(Register reg, Label* not_unique_name,
    950                            Label::Distance distance = Label::kFar) {
    951     JumpIfNotUniqueName(Operand(reg), not_unique_name, distance);
    952   }
    953 
    954   void JumpIfNotUniqueName(Operand operand, Label* not_unique_name,
    955                            Label::Distance distance = Label::kFar);
    956 
    957   void EmitSeqStringSetCharCheck(Register string,
    958                                  Register index,
    959                                  Register value,
    960                                  uint32_t encoding_mask);
    961 
    962   static int SafepointRegisterStackIndex(Register reg) {
    963     return SafepointRegisterStackIndex(reg.code());
    964   }
    965 
    966   // Activation support.
    967   void EnterFrame(StackFrame::Type type);
    968   void LeaveFrame(StackFrame::Type type);
    969 
    970   // Expects object in eax and returns map with validated enum cache
    971   // in eax.  Assumes that any other register can be used as a scratch.
    972   void CheckEnumCache(Label* call_runtime);
    973 
    974   // AllocationMemento support. Arrays may have an associated
    975   // AllocationMemento object that can be checked for in order to pretransition
    976   // to another type.
    977   // On entry, receiver_reg should point to the array object.
    978   // scratch_reg gets clobbered.
    979   // If allocation info is present, conditional code is set to equal.
    980   void TestJSArrayForAllocationMemento(Register receiver_reg,
    981                                        Register scratch_reg,
    982                                        Label* no_memento_found);
    983 
    984   void JumpIfJSArrayHasAllocationMemento(Register receiver_reg,
    985                                          Register scratch_reg,
    986                                          Label* memento_found) {
    987     Label no_memento_found;
    988     TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
    989                                     &no_memento_found);
    990     j(equal, memento_found);
    991     bind(&no_memento_found);
    992   }
    993 
    994   // Jumps to found label if a prototype map has dictionary elements.
    995   void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
    996                                         Register scratch1, Label* found);
    997 
    998  private:
    999   bool generating_stub_;
   1000   bool has_frame_;
   1001   // This handle will be patched with the code object on installation.
   1002   Handle<Object> code_object_;
   1003 
   1004   // Helper functions for generating invokes.
   1005   void InvokePrologue(const ParameterCount& expected,
   1006                       const ParameterCount& actual,
   1007                       Handle<Code> code_constant,
   1008                       const Operand& code_operand,
   1009                       Label* done,
   1010                       bool* definitely_mismatches,
   1011                       InvokeFlag flag,
   1012                       Label::Distance done_distance,
   1013                       const CallWrapper& call_wrapper = NullCallWrapper(),
   1014                       CallKind call_kind = CALL_AS_METHOD);
   1015 
   1016   void EnterExitFramePrologue();
   1017   void EnterExitFrameEpilogue(int argc, bool save_doubles);
   1018 
   1019   void LeaveExitFrameEpilogue(bool restore_context);
   1020 
   1021   // Allocation support helpers.
   1022   void LoadAllocationTopHelper(Register result,
   1023                                Register scratch,
   1024                                AllocationFlags flags);
   1025 
   1026   void UpdateAllocationTopHelper(Register result_end,
   1027                                  Register scratch,
   1028                                  AllocationFlags flags);
   1029 
   1030   // Helper for PopHandleScope.  Allowed to perform a GC and returns
   1031   // NULL if gc_allowed.  Does not perform a GC if !gc_allowed, and
   1032   // possibly returns a failure object indicating an allocation failure.
   1033   MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved,
   1034                                                     Register scratch,
   1035                                                     bool gc_allowed);
   1036 
   1037   // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
   1038   void InNewSpace(Register object,
   1039                   Register scratch,
   1040                   Condition cc,
   1041                   Label* condition_met,
   1042                   Label::Distance condition_met_distance = Label::kFar);
   1043 
   1044   // Helper for finding the mark bits for an address.  Afterwards, the
   1045   // bitmap register points at the word with the mark bits and the mask
   1046   // the position of the first bit.  Uses ecx as scratch and leaves addr_reg
   1047   // unchanged.
   1048   inline void GetMarkBits(Register addr_reg,
   1049                           Register bitmap_reg,
   1050                           Register mask_reg);
   1051 
   1052   // Helper for throwing exceptions.  Compute a handler address and jump to
   1053   // it.  See the implementation for register usage.
   1054   void JumpToHandlerEntry();
   1055 
   1056   // Compute memory operands for safepoint stack slots.
   1057   Operand SafepointRegisterSlot(Register reg);
   1058   static int SafepointRegisterStackIndex(int reg_code);
   1059 
   1060   // Needs access to SafepointRegisterStackIndex for compiled frame
   1061   // traversal.
   1062   friend class StandardFrame;
   1063 };
   1064 
   1065 
   1066 // The code patcher is used to patch (typically) small parts of code e.g. for
   1067 // debugging and other types of instrumentation. When using the code patcher
   1068 // the exact number of bytes specified must be emitted. Is not legal to emit
   1069 // relocation information. If any of these constraints are violated it causes
   1070 // an assertion.
   1071 class CodePatcher {
   1072  public:
   1073   CodePatcher(byte* address, int size);
   1074   virtual ~CodePatcher();
   1075 
   1076   // Macro assembler to emit code.
   1077   MacroAssembler* masm() { return &masm_; }
   1078 
   1079  private:
   1080   byte* address_;  // The address of the code being patched.
   1081   int size_;  // Number of bytes of the expected patch size.
   1082   MacroAssembler masm_;  // Macro assembler used to generate the code.
   1083 };
   1084 
   1085 
   1086 // -----------------------------------------------------------------------------
   1087 // Static helper functions.
   1088 
   1089 // Generate an Operand for loading a field from an object.
   1090 inline Operand FieldOperand(Register object, int offset) {
   1091   return Operand(object, offset - kHeapObjectTag);
   1092 }
   1093 
   1094 
   1095 // Generate an Operand for loading an indexed field from an object.
   1096 inline Operand FieldOperand(Register object,
   1097                             Register index,
   1098                             ScaleFactor scale,
   1099                             int offset) {
   1100   return Operand(object, index, scale, offset - kHeapObjectTag);
   1101 }
   1102 
   1103 
   1104 inline Operand ContextOperand(Register context, int index) {
   1105   return Operand(context, Context::SlotOffset(index));
   1106 }
   1107 
   1108 
   1109 inline Operand GlobalObjectOperand() {
   1110   return ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX);
   1111 }
   1112 
   1113 
   1114 // Generates an Operand for saving parameters after PrepareCallApiFunction.
   1115 Operand ApiParameterOperand(int index);
   1116 
   1117 
   1118 #ifdef GENERATED_CODE_COVERAGE
   1119 extern void LogGeneratedCodeCoverage(const char* file_line);
   1120 #define CODE_COVERAGE_STRINGIFY(x) #x
   1121 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
   1122 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
   1123 #define ACCESS_MASM(masm) {                                               \
   1124     byte* ia32_coverage_function =                                        \
   1125         reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \
   1126     masm->pushfd();                                                       \
   1127     masm->pushad();                                                       \
   1128     masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__)));         \
   1129     masm->call(ia32_coverage_function, RelocInfo::RUNTIME_ENTRY);         \
   1130     masm->pop(eax);                                                       \
   1131     masm->popad();                                                        \
   1132     masm->popfd();                                                        \
   1133   }                                                                       \
   1134   masm->
   1135 #else
   1136 #define ACCESS_MASM(masm) masm->
   1137 #endif
   1138 
   1139 
   1140 } }  // namespace v8::internal
   1141 
   1142 #endif  // V8_IA32_MACRO_ASSEMBLER_IA32_H_
   1143