Home | History | Annotate | Download | only in ia32
      1 // Copyright 2006-2009 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 
     33 namespace v8 {
     34 namespace internal {
     35 
     36 // Convenience for platform-independent signatures.  We do not normally
     37 // distinguish memory operands from other operands on ia32.
     38 typedef Operand MemOperand;
     39 
     40 // Forward declaration.
     41 class JumpTarget;
     42 
     43 // MacroAssembler implements a collection of frequently used macros.
     44 class MacroAssembler: public Assembler {
     45  public:
     46   MacroAssembler(void* buffer, int size);
     47 
     48   // ---------------------------------------------------------------------------
     49   // GC Support
     50 
     51   // Set the remembered set bit for [object+offset].
     52   // object is the object being stored into, value is the object being stored.
     53   // If offset is zero, then the scratch register contains the array index into
     54   // the elements array represented as a Smi.
     55   // All registers are clobbered by the operation.
     56   void RecordWrite(Register object,
     57                    int offset,
     58                    Register value,
     59                    Register scratch);
     60 
     61 #ifdef ENABLE_DEBUGGER_SUPPORT
     62   // ---------------------------------------------------------------------------
     63   // Debugger Support
     64 
     65   void SaveRegistersToMemory(RegList regs);
     66   void RestoreRegistersFromMemory(RegList regs);
     67   void PushRegistersFromMemory(RegList regs);
     68   void PopRegistersToMemory(RegList regs);
     69   void CopyRegistersFromStackToMemory(Register base,
     70                                       Register scratch,
     71                                       RegList regs);
     72   void DebugBreak();
     73 #endif
     74 
     75   // ---------------------------------------------------------------------------
     76   // Stack limit support
     77 
     78   // Do simple test for stack overflow. This doesn't handle an overflow.
     79   void StackLimitCheck(Label* on_stack_limit_hit);
     80 
     81   // ---------------------------------------------------------------------------
     82   // Activation frames
     83 
     84   void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
     85   void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
     86 
     87   void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
     88   void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
     89 
     90   // Enter specific kind of exit frame; either in normal or debug mode.
     91   // Expects the number of arguments in register eax and
     92   // sets up the number of arguments in register edi and the pointer
     93   // to the first argument in register esi.
     94   void EnterExitFrame(ExitFrame::Mode mode);
     95 
     96   void EnterApiExitFrame(ExitFrame::Mode mode, int stack_space, int argc);
     97 
     98   // Leave the current exit frame. Expects the return value in
     99   // register eax:edx (untouched) and the pointer to the first
    100   // argument in register esi.
    101   void LeaveExitFrame(ExitFrame::Mode mode);
    102 
    103   // Find the function context up the context chain.
    104   void LoadContext(Register dst, int context_chain_length);
    105 
    106   // ---------------------------------------------------------------------------
    107   // JavaScript invokes
    108 
    109   // Invoke the JavaScript function code by either calling or jumping.
    110   void InvokeCode(const Operand& code,
    111                   const ParameterCount& expected,
    112                   const ParameterCount& actual,
    113                   InvokeFlag flag);
    114 
    115   void InvokeCode(Handle<Code> code,
    116                   const ParameterCount& expected,
    117                   const ParameterCount& actual,
    118                   RelocInfo::Mode rmode,
    119                   InvokeFlag flag);
    120 
    121   // Invoke the JavaScript function in the given register. Changes the
    122   // current context to the context in the function before invoking.
    123   void InvokeFunction(Register function,
    124                       const ParameterCount& actual,
    125                       InvokeFlag flag);
    126 
    127   void InvokeFunction(JSFunction* function,
    128                       const ParameterCount& actual,
    129                       InvokeFlag flag);
    130 
    131   // Invoke specified builtin JavaScript function. Adds an entry to
    132   // the unresolved list if the name does not resolve.
    133   void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);
    134 
    135   // Store the code object for the given builtin in the target register.
    136   void GetBuiltinEntry(Register target, Builtins::JavaScript id);
    137 
    138   // Expression support
    139   void Set(Register dst, const Immediate& x);
    140   void Set(const Operand& dst, const Immediate& x);
    141 
    142   // Compare object type for heap object.
    143   // Incoming register is heap_object and outgoing register is map.
    144   void CmpObjectType(Register heap_object, InstanceType type, Register map);
    145 
    146   // Compare instance type for map.
    147   void CmpInstanceType(Register map, InstanceType type);
    148 
    149   // Check if the map of an object is equal to a specified map and
    150   // branch to label if not. Skip the smi check if not required
    151   // (object is known to be a heap object)
    152   void CheckMap(Register obj,
    153                 Handle<Map> map,
    154                 Label* fail,
    155                 bool is_heap_object);
    156 
    157   // Check if the object in register heap_object is a string. Afterwards the
    158   // register map contains the object map and the register instance_type
    159   // contains the instance_type. The registers map and instance_type can be the
    160   // same in which case it contains the instance type afterwards. Either of the
    161   // registers map and instance_type can be the same as heap_object.
    162   Condition IsObjectStringType(Register heap_object,
    163                                Register map,
    164                                Register instance_type);
    165 
    166   // FCmp is similar to integer cmp, but requires unsigned
    167   // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
    168   void FCmp();
    169 
    170   // Smi tagging support.
    171   void SmiTag(Register reg) {
    172     ASSERT(kSmiTag == 0);
    173     shl(reg, kSmiTagSize);
    174   }
    175   void SmiUntag(Register reg) {
    176     sar(reg, kSmiTagSize);
    177   }
    178 
    179   // Abort execution if argument is not a number. Used in debug code.
    180   void AbortIfNotNumber(Register object, const char* msg);
    181 
    182   // ---------------------------------------------------------------------------
    183   // Exception handling
    184 
    185   // Push a new try handler and link into try handler chain.  The return
    186   // address must be pushed before calling this helper.
    187   void PushTryHandler(CodeLocation try_location, HandlerType type);
    188 
    189   // Unlink the stack handler on top of the stack from the try handler chain.
    190   void PopTryHandler();
    191 
    192   // ---------------------------------------------------------------------------
    193   // Inline caching support
    194 
    195   // Generates code that verifies that the maps of objects in the
    196   // prototype chain of object hasn't changed since the code was
    197   // generated and branches to the miss label if any map has. If
    198   // necessary the function also generates code for security check
    199   // in case of global object holders. The scratch and holder
    200   // registers are always clobbered, but the object register is only
    201   // clobbered if it the same as the holder register. The function
    202   // returns a register containing the holder - either object_reg or
    203   // holder_reg.
    204   // The function can optionally (when save_at_depth !=
    205   // kInvalidProtoDepth) save the object at the given depth by moving
    206   // it to [esp + kPointerSize].
    207   Register CheckMaps(JSObject* object, Register object_reg,
    208                      JSObject* holder, Register holder_reg,
    209                      Register scratch,
    210                      int save_at_depth,
    211                      Label* miss);
    212 
    213   // Generate code for checking access rights - used for security checks
    214   // on access to global objects across environments. The holder register
    215   // is left untouched, but the scratch register is clobbered.
    216   void CheckAccessGlobalProxy(Register holder_reg,
    217                               Register scratch,
    218                               Label* miss);
    219 
    220 
    221   // ---------------------------------------------------------------------------
    222   // Allocation support
    223 
    224   // Allocate an object in new space. If the new space is exhausted control
    225   // continues at the gc_required label. The allocated object is returned in
    226   // result and end of the new object is returned in result_end. The register
    227   // scratch can be passed as no_reg in which case an additional object
    228   // reference will be added to the reloc info. The returned pointers in result
    229   // and result_end have not yet been tagged as heap objects. If
    230   // result_contains_top_on_entry is true the content of result is known to be
    231   // the allocation top on entry (could be result_end from a previous call to
    232   // AllocateInNewSpace). If result_contains_top_on_entry is true scratch
    233   // should be no_reg as it is never used.
    234   void AllocateInNewSpace(int object_size,
    235                           Register result,
    236                           Register result_end,
    237                           Register scratch,
    238                           Label* gc_required,
    239                           AllocationFlags flags);
    240 
    241   void AllocateInNewSpace(int header_size,
    242                           ScaleFactor element_size,
    243                           Register element_count,
    244                           Register result,
    245                           Register result_end,
    246                           Register scratch,
    247                           Label* gc_required,
    248                           AllocationFlags flags);
    249 
    250   void AllocateInNewSpace(Register object_size,
    251                           Register result,
    252                           Register result_end,
    253                           Register scratch,
    254                           Label* gc_required,
    255                           AllocationFlags flags);
    256 
    257   // Undo allocation in new space. The object passed and objects allocated after
    258   // it will no longer be allocated. Make sure that no pointers are left to the
    259   // object(s) no longer allocated as they would be invalid when allocation is
    260   // un-done.
    261   void UndoAllocationInNewSpace(Register object);
    262 
    263   // Allocate a heap number in new space with undefined value. The
    264   // register scratch2 can be passed as no_reg; the others must be
    265   // valid registers. Returns tagged pointer in result register, or
    266   // jumps to gc_required if new space is full.
    267   void AllocateHeapNumber(Register result,
    268                           Register scratch1,
    269                           Register scratch2,
    270                           Label* gc_required);
    271 
    272   // Allocate a sequential string. All the header fields of the string object
    273   // are initialized.
    274   void AllocateTwoByteString(Register result,
    275                              Register length,
    276                              Register scratch1,
    277                              Register scratch2,
    278                              Register scratch3,
    279                              Label* gc_required);
    280   void AllocateAsciiString(Register result,
    281                            Register length,
    282                            Register scratch1,
    283                            Register scratch2,
    284                            Register scratch3,
    285                            Label* gc_required);
    286 
    287   // Allocate a raw cons string object. Only the map field of the result is
    288   // initialized.
    289   void AllocateConsString(Register result,
    290                           Register scratch1,
    291                           Register scratch2,
    292                           Label* gc_required);
    293   void AllocateAsciiConsString(Register result,
    294                                Register scratch1,
    295                                Register scratch2,
    296                                Label* gc_required);
    297 
    298   // ---------------------------------------------------------------------------
    299   // Support functions.
    300 
    301   // Check if result is zero and op is negative.
    302   void NegativeZeroTest(Register result, Register op, Label* then_label);
    303 
    304   // Check if result is zero and op is negative in code using jump targets.
    305   void NegativeZeroTest(CodeGenerator* cgen,
    306                         Register result,
    307                         Register op,
    308                         JumpTarget* then_target);
    309 
    310   // Check if result is zero and any of op1 and op2 are negative.
    311   // Register scratch is destroyed, and it must be different from op2.
    312   void NegativeZeroTest(Register result, Register op1, Register op2,
    313                         Register scratch, Label* then_label);
    314 
    315   // Try to get function prototype of a function and puts the value in
    316   // the result register. Checks that the function really is a
    317   // function and jumps to the miss label if the fast checks fail. The
    318   // function register will be untouched; the other registers may be
    319   // clobbered.
    320   void TryGetFunctionPrototype(Register function,
    321                                Register result,
    322                                Register scratch,
    323                                Label* miss);
    324 
    325   // Generates code for reporting that an illegal operation has
    326   // occurred.
    327   void IllegalOperation(int num_arguments);
    328 
    329   // ---------------------------------------------------------------------------
    330   // Runtime calls
    331 
    332   // Call a code stub.  Generate the code if necessary.
    333   void CallStub(CodeStub* stub);
    334 
    335   // Call a code stub and return the code object called.  Try to generate
    336   // the code if necessary.  Do not perform a GC but instead return a retry
    337   // after GC failure.
    338   Object* TryCallStub(CodeStub* stub);
    339 
    340   // Tail call a code stub (jump).  Generate the code if necessary.
    341   void TailCallStub(CodeStub* stub);
    342 
    343   // Tail call a code stub (jump) and return the code object called.  Try to
    344   // generate the code if necessary.  Do not perform a GC but instead return
    345   // a retry after GC failure.
    346   Object* TryTailCallStub(CodeStub* stub);
    347 
    348   // Return from a code stub after popping its arguments.
    349   void StubReturn(int argc);
    350 
    351   // Call a runtime routine.
    352   // Eventually this should be used for all C calls.
    353   void CallRuntime(Runtime::Function* f, int num_arguments);
    354 
    355   // Call a runtime function, returning the CodeStub object called.
    356   // Try to generate the stub code if necessary.  Do not perform a GC
    357   // but instead return a retry after GC failure.
    358   Object* TryCallRuntime(Runtime::Function* f, int num_arguments);
    359 
    360   // Convenience function: Same as above, but takes the fid instead.
    361   void CallRuntime(Runtime::FunctionId id, int num_arguments);
    362 
    363   // Convenience function: call an external reference.
    364   void CallExternalReference(ExternalReference ref, int num_arguments);
    365 
    366   // Convenience function: Same as above, but takes the fid instead.
    367   Object* TryCallRuntime(Runtime::FunctionId id, int num_arguments);
    368 
    369   // Tail call of a runtime routine (jump).
    370   // Like JumpToRuntime, but also takes care of passing the number
    371   // of arguments.
    372   void TailCallRuntime(const ExternalReference& ext,
    373                        int num_arguments,
    374                        int result_size);
    375 
    376   void PushHandleScope(Register scratch);
    377 
    378   // Pops a handle scope using the specified scratch register and
    379   // ensuring that saved register, it is not no_reg, is left unchanged.
    380   void PopHandleScope(Register saved, Register scratch);
    381 
    382   // As PopHandleScope, but does not perform a GC.  Instead, returns a
    383   // retry after GC failure object if GC is necessary.
    384   Object* TryPopHandleScope(Register saved, Register scratch);
    385 
    386   // Jump to a runtime routine.
    387   void JumpToRuntime(const ExternalReference& ext);
    388 
    389 
    390   // ---------------------------------------------------------------------------
    391   // Utilities
    392 
    393   void Ret();
    394 
    395   // Emit code to discard a non-negative number of pointer-sized elements
    396   // from the stack, clobbering only the esp register.
    397   void Drop(int element_count);
    398 
    399   void Call(Label* target) { call(target); }
    400 
    401   void Move(Register target, Handle<Object> value);
    402 
    403   Handle<Object> CodeObject() { return code_object_; }
    404 
    405 
    406   // ---------------------------------------------------------------------------
    407   // StatsCounter support
    408 
    409   void SetCounter(StatsCounter* counter, int value);
    410   void IncrementCounter(StatsCounter* counter, int value);
    411   void DecrementCounter(StatsCounter* counter, int value);
    412   void IncrementCounter(Condition cc, StatsCounter* counter, int value);
    413   void DecrementCounter(Condition cc, StatsCounter* counter, int value);
    414 
    415 
    416   // ---------------------------------------------------------------------------
    417   // Debugging
    418 
    419   // Calls Abort(msg) if the condition cc is not satisfied.
    420   // Use --debug_code to enable.
    421   void Assert(Condition cc, const char* msg);
    422 
    423   // Like Assert(), but always enabled.
    424   void Check(Condition cc, const char* msg);
    425 
    426   // Print a message to stdout and abort execution.
    427   void Abort(const char* msg);
    428 
    429   // Verify restrictions about code generated in stubs.
    430   void set_generating_stub(bool value) { generating_stub_ = value; }
    431   bool generating_stub() { return generating_stub_; }
    432   void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
    433   bool allow_stub_calls() { return allow_stub_calls_; }
    434 
    435   // ---------------------------------------------------------------------------
    436   // String utilities.
    437 
    438   // Check whether the instance type represents a flat ascii string. Jump to the
    439   // label if not. If the instance type can be scratched specify same register
    440   // for both instance type and scratch.
    441   void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type,
    442                                               Register scratch,
    443                                               Label *on_not_flat_ascii_string);
    444 
    445   // Checks if both objects are sequential ASCII strings, and jumps to label
    446   // if either is not.
    447   void JumpIfNotBothSequentialAsciiStrings(Register object1,
    448                                            Register object2,
    449                                            Register scratch1,
    450                                            Register scratch2,
    451                                            Label *on_not_flat_ascii_strings);
    452 
    453  private:
    454   bool generating_stub_;
    455   bool allow_stub_calls_;
    456   // This handle will be patched with the code object on installation.
    457   Handle<Object> code_object_;
    458 
    459   // Helper functions for generating invokes.
    460   void InvokePrologue(const ParameterCount& expected,
    461                       const ParameterCount& actual,
    462                       Handle<Code> code_constant,
    463                       const Operand& code_operand,
    464                       Label* done,
    465                       InvokeFlag flag);
    466 
    467   // Activation support.
    468   void EnterFrame(StackFrame::Type type);
    469   void LeaveFrame(StackFrame::Type type);
    470 
    471   void EnterExitFramePrologue(ExitFrame::Mode mode);
    472   void EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc);
    473 
    474   // Allocation support helpers.
    475   void LoadAllocationTopHelper(Register result,
    476                                Register result_end,
    477                                Register scratch,
    478                                AllocationFlags flags);
    479   void UpdateAllocationTopHelper(Register result_end, Register scratch);
    480 
    481   // Helper for PopHandleScope.  Allowed to perform a GC and returns
    482   // NULL if gc_allowed.  Does not perform a GC if !gc_allowed, and
    483   // possibly returns a failure object indicating an allocation failure.
    484   Object* PopHandleScopeHelper(Register saved,
    485                                Register scratch,
    486                                bool gc_allowed);
    487 };
    488 
    489 
    490 // The code patcher is used to patch (typically) small parts of code e.g. for
    491 // debugging and other types of instrumentation. When using the code patcher
    492 // the exact number of bytes specified must be emitted. Is not legal to emit
    493 // relocation information. If any of these constraints are violated it causes
    494 // an assertion.
    495 class CodePatcher {
    496  public:
    497   CodePatcher(byte* address, int size);
    498   virtual ~CodePatcher();
    499 
    500   // Macro assembler to emit code.
    501   MacroAssembler* masm() { return &masm_; }
    502 
    503  private:
    504   byte* address_;  // The address of the code being patched.
    505   int size_;  // Number of bytes of the expected patch size.
    506   MacroAssembler masm_;  // Macro assembler used to generate the code.
    507 };
    508 
    509 
    510 // -----------------------------------------------------------------------------
    511 // Static helper functions.
    512 
    513 // Generate an Operand for loading a field from an object.
    514 static inline Operand FieldOperand(Register object, int offset) {
    515   return Operand(object, offset - kHeapObjectTag);
    516 }
    517 
    518 
    519 // Generate an Operand for loading an indexed field from an object.
    520 static inline Operand FieldOperand(Register object,
    521                                    Register index,
    522                                    ScaleFactor scale,
    523                                    int offset) {
    524   return Operand(object, index, scale, offset - kHeapObjectTag);
    525 }
    526 
    527 
    528 #ifdef GENERATED_CODE_COVERAGE
    529 extern void LogGeneratedCodeCoverage(const char* file_line);
    530 #define CODE_COVERAGE_STRINGIFY(x) #x
    531 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
    532 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
    533 #define ACCESS_MASM(masm) {                                               \
    534     byte* ia32_coverage_function =                                        \
    535         reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \
    536     masm->pushfd();                                                       \
    537     masm->pushad();                                                       \
    538     masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__)));         \
    539     masm->call(ia32_coverage_function, RelocInfo::RUNTIME_ENTRY);         \
    540     masm->pop(eax);                                                       \
    541     masm->popad();                                                        \
    542     masm->popfd();                                                        \
    543   }                                                                       \
    544   masm->
    545 #else
    546 #define ACCESS_MASM(masm) masm->
    547 #endif
    548 
    549 
    550 } }  // namespace v8::internal
    551 
    552 #endif  // V8_IA32_MACRO_ASSEMBLER_IA32_H_
    553