00001 // Copyright 2006-2008 the V8 project authors. All rights reserved. 00002 // Redistribution and use in source and binary forms, with or without 00003 // modification, are permitted provided that the following conditions are 00004 // met: 00005 // 00006 // * Redistributions of source code must retain the above copyright 00007 // notice, this list of conditions and the following disclaimer. 00008 // * Redistributions in binary form must reproduce the above 00009 // copyright notice, this list of conditions and the following 00010 // disclaimer in the documentation and/or other materials provided 00011 // with the distribution. 00012 // * Neither the name of Google Inc. nor the names of its 00013 // contributors may be used to endorse or promote products derived 00014 // from this software without specific prior written permission. 00015 // 00016 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00017 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00018 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00019 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00020 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00021 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00022 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00023 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00024 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00026 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 00028 #ifndef V8_MACRO_ASSEMBLER_IA32_H_ 00029 #define V8_MACRO_ASSEMBLER_IA32_H_ 00030 00031 #include "assembler.h" 00032 00033 namespace v8 { namespace internal { 00034 00035 00036 // Helper type to make boolean flag easier to read at call-site. 00037 enum InvokeFlag { 00038 CALL_FUNCTION, 00039 JUMP_FUNCTION 00040 }; 00041 00042 enum CodeLocation { 00043 IN_JAVASCRIPT, 00044 IN_JS_ENTRY, 00045 IN_C_ENTRY 00046 }; 00047 00048 enum HandlerType { 00049 TRY_CATCH_HANDLER, 00050 TRY_FINALLY_HANDLER, 00051 JS_ENTRY_HANDLER 00052 }; 00053 00054 00055 // MacroAssembler implements a collection of frequently used macros. 00056 class MacroAssembler: public Assembler { 00057 public: 00058 MacroAssembler(void* buffer, int size); 00059 00060 // --------------------------------------------------------------------------- 00061 // GC Support 00062 00063 // Set the remembered set bit for [object+offset]. 00064 // object is the object being stored into, value is the object being stored. 00065 // If offset is zero, then the scratch register contains the array index into 00066 // the elements array represented as a Smi. 00067 // All registers are clobbered by the operation. 00068 void RecordWrite(Register object, 00069 int offset, 00070 Register value, 00071 Register scratch); 00072 00073 00074 // --------------------------------------------------------------------------- 00075 // Debugger Support 00076 00077 void SaveRegistersToMemory(RegList regs); 00078 void RestoreRegistersFromMemory(RegList regs); 00079 void PushRegistersFromMemory(RegList regs); 00080 void PopRegistersToMemory(RegList regs); 00081 void CopyRegistersFromStackToMemory(Register base, 00082 Register scratch, 00083 RegList regs); 00084 00085 00086 // --------------------------------------------------------------------------- 00087 // Activation frames 00088 00089 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); } 00090 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); } 00091 00092 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); } 00093 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); } 00094 00095 // Enter specific kind of exit frame; either EXIT or 00096 // EXIT_DEBUG. Expects the number of arguments in register eax and 00097 // sets up the number of arguments in register edi and the pointer 00098 // to the first argument in register esi. 00099 void EnterExitFrame(StackFrame::Type type); 00100 00101 // Leave the current exit frame. Expects the return value in 00102 // register eax:edx (untouched) and the pointer to the first 00103 // argument in register esi. 00104 void LeaveExitFrame(StackFrame::Type type); 00105 00106 00107 // --------------------------------------------------------------------------- 00108 // JavaScript invokes 00109 00110 // Invoke the JavaScript function code by either calling or jumping. 00111 void InvokeCode(const Operand& code, 00112 const ParameterCount& expected, 00113 const ParameterCount& actual, 00114 InvokeFlag flag); 00115 00116 void InvokeCode(Handle<Code> code, 00117 const ParameterCount& expected, 00118 const ParameterCount& actual, 00119 RelocInfo::Mode rmode, 00120 InvokeFlag flag); 00121 00122 // Invoke the JavaScript function in the given register. Changes the 00123 // current context to the context in the function before invoking. 00124 void InvokeFunction(Register function, 00125 const ParameterCount& actual, 00126 InvokeFlag flag); 00127 00128 // Invoke specified builtin JavaScript function. Adds an entry to 00129 // the unresolved list if the name does not resolve. 00130 void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag); 00131 00132 // Store the code object for the given builtin in the target register. 00133 void GetBuiltinEntry(Register target, Builtins::JavaScript id); 00134 00135 // Expression support 00136 void Set(Register dst, const Immediate& x); 00137 void Set(const Operand& dst, const Immediate& x); 00138 00139 // FCmp is similar to integer cmp, but requires unsigned 00140 // jcc instructions (je, ja, jae, jb, jbe, je, and jz). 00141 void FCmp(); 00142 00143 // --------------------------------------------------------------------------- 00144 // Exception handling 00145 00146 // Push a new try handler and link into try handler chain. 00147 // The return address must be pushed before calling this helper. 00148 // On exit, eax contains TOS (next_sp). 00149 void PushTryHandler(CodeLocation try_location, HandlerType type); 00150 00151 00152 // --------------------------------------------------------------------------- 00153 // Inline caching support 00154 00155 // Generates code that verifies that the maps of objects in the 00156 // prototype chain of object hasn't changed since the code was 00157 // generated and branches to the miss label if any map has. If 00158 // necessary the function also generates code for security check 00159 // in case of global object holders. The scratch and holder 00160 // registers are always clobbered, but the object register is only 00161 // clobbered if it the same as the holder register. The function 00162 // returns a register containing the holder - either object_reg or 00163 // holder_reg. 00164 Register CheckMaps(JSObject* object, Register object_reg, 00165 JSObject* holder, Register holder_reg, 00166 Register scratch, Label* miss); 00167 00168 // Generate code for checking access rights - used for security checks 00169 // on access to global objects across environments. The holder register 00170 // is left untouched, but the scratch register is clobbered. 00171 void CheckAccessGlobalProxy(Register holder_reg, 00172 Register scratch, 00173 Label* miss); 00174 00175 00176 // --------------------------------------------------------------------------- 00177 // Support functions. 00178 00179 // Check if result is zero and op is negative. 00180 void NegativeZeroTest(Register result, Register op, Label* then_label); 00181 00182 // Check if result is zero and any of op1 and op2 are negative. 00183 // Register scratch is destroyed, and it must be different from op2. 00184 void NegativeZeroTest(Register result, Register op1, Register op2, 00185 Register scratch, Label* then_label); 00186 00187 // Try to get function prototype of a function and puts the value in 00188 // the result register. Checks that the function really is a 00189 // function and jumps to the miss label if the fast checks fail. The 00190 // function register will be untouched; the other registers may be 00191 // clobbered. 00192 void TryGetFunctionPrototype(Register function, 00193 Register result, 00194 Register scratch, 00195 Label* miss); 00196 00197 // Generates code for reporting that an illegal operation has 00198 // occurred. 00199 void IllegalOperation(int num_arguments); 00200 00201 // --------------------------------------------------------------------------- 00202 // Runtime calls 00203 00204 // Call a code stub. 00205 void CallStub(CodeStub* stub); 00206 00207 // Return from a code stub after popping its arguments. 00208 void StubReturn(int argc); 00209 00210 // Call a runtime routine. 00211 // Eventually this should be used for all C calls. 00212 void CallRuntime(Runtime::Function* f, int num_arguments); 00213 00214 // Convenience function: Same as above, but takes the fid instead. 00215 void CallRuntime(Runtime::FunctionId id, int num_arguments); 00216 00217 // Tail call of a runtime routine (jump). 00218 // Like JumpToBuiltin, but also takes care of passing the number 00219 // of arguments. 00220 void TailCallRuntime(const ExternalReference& ext, int num_arguments); 00221 00222 // Jump to the builtin routine. 00223 void JumpToBuiltin(const ExternalReference& ext); 00224 00225 00226 // --------------------------------------------------------------------------- 00227 // Utilities 00228 00229 void Ret(); 00230 00231 struct Unresolved { 00232 int pc; 00233 uint32_t flags; // see Bootstrapper::FixupFlags decoders/encoders. 00234 const char* name; 00235 }; 00236 List<Unresolved>* unresolved() { return &unresolved_; } 00237 00238 00239 // --------------------------------------------------------------------------- 00240 // StatsCounter support 00241 00242 void SetCounter(StatsCounter* counter, int value); 00243 void IncrementCounter(StatsCounter* counter, int value); 00244 void DecrementCounter(StatsCounter* counter, int value); 00245 00246 00247 // --------------------------------------------------------------------------- 00248 // Debugging 00249 00250 // Calls Abort(msg) if the condition cc is not satisfied. 00251 // Use --debug_code to enable. 00252 void Assert(Condition cc, const char* msg); 00253 00254 // Like Assert(), but always enabled. 00255 void Check(Condition cc, const char* msg); 00256 00257 // Print a message to stdout and abort execution. 00258 void Abort(const char* msg); 00259 00260 // Verify restrictions about code generated in stubs. 00261 void set_generating_stub(bool value) { generating_stub_ = value; } 00262 bool generating_stub() { return generating_stub_; } 00263 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; } 00264 bool allow_stub_calls() { return allow_stub_calls_; } 00265 00266 private: 00267 List<Unresolved> unresolved_; 00268 bool generating_stub_; 00269 bool allow_stub_calls_; 00270 00271 // Helper functions for generating invokes. 00272 void InvokePrologue(const ParameterCount& expected, 00273 const ParameterCount& actual, 00274 Handle<Code> code_constant, 00275 const Operand& code_operand, 00276 Label* done, 00277 InvokeFlag flag); 00278 00279 // Get the code for the given builtin. Returns if able to resolve 00280 // the function in the 'resolved' flag. 00281 Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved); 00282 00283 // Activation support. 00284 void EnterFrame(StackFrame::Type type); 00285 void LeaveFrame(StackFrame::Type type); 00286 }; 00287 00288 00289 // The code patcher is used to patch (typically) small parts of code e.g. for 00290 // debugging and other types of instrumentation. When using the code patcher 00291 // the exact number of bytes specified must be emitted. Is not legal to emit 00292 // relocation information. If any of these constraints are violated it causes 00293 // an assertion. 00294 class CodePatcher { 00295 public: 00296 CodePatcher(byte* address, int size); 00297 virtual ~CodePatcher(); 00298 00299 // Macro assembler to emit code. 00300 MacroAssembler* masm() { return &masm_; } 00301 00302 private: 00303 byte* address_; // The address of the code being patched. 00304 int size_; // Number of bytes of the expected patch size. 00305 MacroAssembler masm_; // Macro assembler used to generate the code. 00306 }; 00307 00308 // ----------------------------------------------------------------------------- 00309 // Static helper functions. 00310 00311 // Generate an Operand for loading a field from an object. 00312 static inline Operand FieldOperand(Register object, int offset) { 00313 return Operand(object, offset - kHeapObjectTag); 00314 } 00315 00316 00317 // Generate an Operand for loading an indexed field from an object. 00318 static inline Operand FieldOperand(Register object, 00319 Register index, 00320 ScaleFactor scale, 00321 int offset) { 00322 return Operand(object, index, scale, offset - kHeapObjectTag); 00323 } 00324 00325 00326 } } // namespace v8::internal 00327 00328 #endif // V8_MACRO_ASSEMBLER_IA32_H_