blob: a41d42e82b4ba2c7b41ba7ec135a827da3df2f58 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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
33namespace v8 {
34namespace internal {
35
36// Forward declaration.
37class JumpTarget;
38
39
40// MacroAssembler implements a collection of frequently used macros.
41class MacroAssembler: public Assembler {
42 public:
43 MacroAssembler(void* buffer, int size);
44
45 // ---------------------------------------------------------------------------
46 // GC Support
47
48 // Set the remembered set bit for [object+offset].
49 // object is the object being stored into, value is the object being stored.
50 // If offset is zero, then the scratch register contains the array index into
51 // the elements array represented as a Smi.
52 // All registers are clobbered by the operation.
53 void RecordWrite(Register object,
54 int offset,
55 Register value,
56 Register scratch);
57
58#ifdef ENABLE_DEBUGGER_SUPPORT
59 // ---------------------------------------------------------------------------
60 // Debugger Support
61
62 void SaveRegistersToMemory(RegList regs);
63 void RestoreRegistersFromMemory(RegList regs);
64 void PushRegistersFromMemory(RegList regs);
65 void PopRegistersToMemory(RegList regs);
66 void CopyRegistersFromStackToMemory(Register base,
67 Register scratch,
68 RegList regs);
69#endif
70
71 // ---------------------------------------------------------------------------
Steve Blockd0582a62009-12-15 09:54:21 +000072 // Stack limit support
73
74 // Do simple test for stack overflow. This doesn't handle an overflow.
75 void StackLimitCheck(Label* on_stack_limit_hit);
76
77 // ---------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +000078 // Activation frames
79
80 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
81 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
82
83 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
84 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
85
Steve Blockd0582a62009-12-15 09:54:21 +000086 // Enter specific kind of exit frame; either in normal or debug mode.
87 // Expects the number of arguments in register eax and
Steve Blocka7e24c12009-10-30 11:49:00 +000088 // sets up the number of arguments in register edi and the pointer
89 // to the first argument in register esi.
Steve Blockd0582a62009-12-15 09:54:21 +000090 void EnterExitFrame(ExitFrame::Mode mode);
91
92 void EnterApiExitFrame(ExitFrame::Mode mode, int stack_space, int argc);
Steve Blocka7e24c12009-10-30 11:49:00 +000093
94 // Leave the current exit frame. Expects the return value in
95 // register eax:edx (untouched) and the pointer to the first
96 // argument in register esi.
Steve Blockd0582a62009-12-15 09:54:21 +000097 void LeaveExitFrame(ExitFrame::Mode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +000098
Steve Blockd0582a62009-12-15 09:54:21 +000099 // Find the function context up the context chain.
100 void LoadContext(Register dst, int context_chain_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000101
102 // ---------------------------------------------------------------------------
103 // JavaScript invokes
104
105 // Invoke the JavaScript function code by either calling or jumping.
106 void InvokeCode(const Operand& code,
107 const ParameterCount& expected,
108 const ParameterCount& actual,
109 InvokeFlag flag);
110
111 void InvokeCode(Handle<Code> code,
112 const ParameterCount& expected,
113 const ParameterCount& actual,
114 RelocInfo::Mode rmode,
115 InvokeFlag flag);
116
117 // Invoke the JavaScript function in the given register. Changes the
118 // current context to the context in the function before invoking.
119 void InvokeFunction(Register function,
120 const ParameterCount& actual,
121 InvokeFlag flag);
122
123 // Invoke specified builtin JavaScript function. Adds an entry to
124 // the unresolved list if the name does not resolve.
125 void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);
126
127 // Store the code object for the given builtin in the target register.
128 void GetBuiltinEntry(Register target, Builtins::JavaScript id);
129
130 // Expression support
131 void Set(Register dst, const Immediate& x);
132 void Set(const Operand& dst, const Immediate& x);
133
134 // Compare object type for heap object.
135 // Incoming register is heap_object and outgoing register is map.
136 void CmpObjectType(Register heap_object, InstanceType type, Register map);
137
138 // Compare instance type for map.
139 void CmpInstanceType(Register map, InstanceType type);
140
141 // FCmp is similar to integer cmp, but requires unsigned
142 // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
143 void FCmp();
144
145 // ---------------------------------------------------------------------------
146 // Exception handling
147
148 // Push a new try handler and link into try handler chain. The return
149 // address must be pushed before calling this helper.
150 void PushTryHandler(CodeLocation try_location, HandlerType type);
151
152
153 // ---------------------------------------------------------------------------
154 // Inline caching support
155
156 // Generates code that verifies that the maps of objects in the
157 // prototype chain of object hasn't changed since the code was
158 // generated and branches to the miss label if any map has. If
159 // necessary the function also generates code for security check
160 // in case of global object holders. The scratch and holder
161 // registers are always clobbered, but the object register is only
162 // clobbered if it the same as the holder register. The function
163 // returns a register containing the holder - either object_reg or
164 // holder_reg.
165 Register CheckMaps(JSObject* object, Register object_reg,
166 JSObject* holder, Register holder_reg,
167 Register scratch, Label* miss);
168
169 // Generate code for checking access rights - used for security checks
170 // on access to global objects across environments. The holder register
171 // is left untouched, but the scratch register is clobbered.
172 void CheckAccessGlobalProxy(Register holder_reg,
173 Register scratch,
174 Label* miss);
175
176
177 // ---------------------------------------------------------------------------
178 // Allocation support
179
180 // Allocate an object in new space. If the new space is exhausted control
181 // continues at the gc_required label. The allocated object is returned in
182 // result and end of the new object is returned in result_end. The register
183 // scratch can be passed as no_reg in which case an additional object
184 // reference will be added to the reloc info. The returned pointers in result
185 // and result_end have not yet been tagged as heap objects. If
Steve Blockd0582a62009-12-15 09:54:21 +0000186 // result_contains_top_on_entry is true the content of result is known to be
Steve Blocka7e24c12009-10-30 11:49:00 +0000187 // the allocation top on entry (could be result_end from a previous call to
188 // AllocateInNewSpace). If result_contains_top_on_entry is true scratch
189 // should be no_reg as it is never used.
190 void AllocateInNewSpace(int object_size,
191 Register result,
192 Register result_end,
193 Register scratch,
194 Label* gc_required,
195 AllocationFlags flags);
196
197 void AllocateInNewSpace(int header_size,
198 ScaleFactor element_size,
199 Register element_count,
200 Register result,
201 Register result_end,
202 Register scratch,
203 Label* gc_required,
204 AllocationFlags flags);
205
206 void AllocateInNewSpace(Register object_size,
207 Register result,
208 Register result_end,
209 Register scratch,
210 Label* gc_required,
211 AllocationFlags flags);
212
213 // Undo allocation in new space. The object passed and objects allocated after
214 // it will no longer be allocated. Make sure that no pointers are left to the
215 // object(s) no longer allocated as they would be invalid when allocation is
216 // un-done.
217 void UndoAllocationInNewSpace(Register object);
218
Steve Block3ce2e202009-11-05 08:53:23 +0000219 // Allocate a heap number in new space with undefined value. The
220 // register scratch2 can be passed as no_reg; the others must be
221 // valid registers. Returns tagged pointer in result register, or
222 // jumps to gc_required if new space is full.
223 void AllocateHeapNumber(Register result,
224 Register scratch1,
225 Register scratch2,
226 Label* gc_required);
227
Steve Blockd0582a62009-12-15 09:54:21 +0000228 // Allocate a sequential string. All the header fields of the string object
229 // are initialized.
230 void AllocateTwoByteString(Register result,
231 Register length,
232 Register scratch1,
233 Register scratch2,
234 Register scratch3,
235 Label* gc_required);
236 void AllocateAsciiString(Register result,
237 Register length,
238 Register scratch1,
239 Register scratch2,
240 Register scratch3,
241 Label* gc_required);
242
243 // Allocate a raw cons string object. Only the map field of the result is
244 // initialized.
245 void AllocateConsString(Register result,
246 Register scratch1,
247 Register scratch2,
248 Label* gc_required);
249 void AllocateAsciiConsString(Register result,
250 Register scratch1,
251 Register scratch2,
252 Label* gc_required);
253
Steve Blocka7e24c12009-10-30 11:49:00 +0000254 // ---------------------------------------------------------------------------
255 // Support functions.
256
257 // Check if result is zero and op is negative.
258 void NegativeZeroTest(Register result, Register op, Label* then_label);
259
260 // Check if result is zero and op is negative in code using jump targets.
261 void NegativeZeroTest(CodeGenerator* cgen,
262 Register result,
263 Register op,
264 JumpTarget* then_target);
265
266 // Check if result is zero and any of op1 and op2 are negative.
267 // Register scratch is destroyed, and it must be different from op2.
268 void NegativeZeroTest(Register result, Register op1, Register op2,
269 Register scratch, Label* then_label);
270
271 // Try to get function prototype of a function and puts the value in
272 // the result register. Checks that the function really is a
273 // function and jumps to the miss label if the fast checks fail. The
274 // function register will be untouched; the other registers may be
275 // clobbered.
276 void TryGetFunctionPrototype(Register function,
277 Register result,
278 Register scratch,
279 Label* miss);
280
281 // Generates code for reporting that an illegal operation has
282 // occurred.
283 void IllegalOperation(int num_arguments);
284
285 // ---------------------------------------------------------------------------
286 // Runtime calls
287
288 // Call a code stub.
289 void CallStub(CodeStub* stub);
290
Steve Blockd0582a62009-12-15 09:54:21 +0000291 // Tail call a code stub (jump).
292 void TailCallStub(CodeStub* stub);
293
Steve Blocka7e24c12009-10-30 11:49:00 +0000294 // Return from a code stub after popping its arguments.
295 void StubReturn(int argc);
296
297 // Call a runtime routine.
298 // Eventually this should be used for all C calls.
299 void CallRuntime(Runtime::Function* f, int num_arguments);
300
301 // Convenience function: Same as above, but takes the fid instead.
302 void CallRuntime(Runtime::FunctionId id, int num_arguments);
303
304 // Tail call of a runtime routine (jump).
305 // Like JumpToRuntime, but also takes care of passing the number
306 // of arguments.
307 void TailCallRuntime(const ExternalReference& ext,
308 int num_arguments,
309 int result_size);
310
Steve Blockd0582a62009-12-15 09:54:21 +0000311 void PushHandleScope(Register scratch);
312
313 // Pops a handle scope using the specified scratch register and
314 // ensuring that saved register, it is not no_reg, is left unchanged.
315 void PopHandleScope(Register saved, Register scratch);
316
Steve Blocka7e24c12009-10-30 11:49:00 +0000317 // Jump to a runtime routine.
318 void JumpToRuntime(const ExternalReference& ext);
319
320
321 // ---------------------------------------------------------------------------
322 // Utilities
323
324 void Ret();
325
326 struct Unresolved {
327 int pc;
328 uint32_t flags; // see Bootstrapper::FixupFlags decoders/encoders.
329 const char* name;
330 };
331 List<Unresolved>* unresolved() { return &unresolved_; }
332
333 Handle<Object> CodeObject() { return code_object_; }
334
335
336 // ---------------------------------------------------------------------------
337 // StatsCounter support
338
339 void SetCounter(StatsCounter* counter, int value);
340 void IncrementCounter(StatsCounter* counter, int value);
341 void DecrementCounter(StatsCounter* counter, int value);
342
343
344 // ---------------------------------------------------------------------------
345 // Debugging
346
347 // Calls Abort(msg) if the condition cc is not satisfied.
348 // Use --debug_code to enable.
349 void Assert(Condition cc, const char* msg);
350
351 // Like Assert(), but always enabled.
352 void Check(Condition cc, const char* msg);
353
354 // Print a message to stdout and abort execution.
355 void Abort(const char* msg);
356
357 // Verify restrictions about code generated in stubs.
358 void set_generating_stub(bool value) { generating_stub_ = value; }
359 bool generating_stub() { return generating_stub_; }
360 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
361 bool allow_stub_calls() { return allow_stub_calls_; }
362
363 private:
364 List<Unresolved> unresolved_;
365 bool generating_stub_;
366 bool allow_stub_calls_;
367 Handle<Object> code_object_; // This handle will be patched with the
368 // code object on installation.
369
370 // Helper functions for generating invokes.
371 void InvokePrologue(const ParameterCount& expected,
372 const ParameterCount& actual,
373 Handle<Code> code_constant,
374 const Operand& code_operand,
375 Label* done,
376 InvokeFlag flag);
377
378 // Prepares for a call or jump to a builtin by doing two things:
379 // 1. Emits code that fetches the builtin's function object from the context
380 // at runtime, and puts it in the register rdi.
381 // 2. Fetches the builtin's code object, and returns it in a handle, at
382 // compile time, so that later code can emit instructions to jump or call
383 // the builtin directly. If the code object has not yet been created, it
384 // returns the builtin code object for IllegalFunction, and sets the
385 // output parameter "resolved" to false. Code that uses the return value
386 // should then add the address and the builtin name to the list of fixups
387 // called unresolved_, which is fixed up by the bootstrapper.
388 Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
389
390 // Activation support.
391 void EnterFrame(StackFrame::Type type);
392 void LeaveFrame(StackFrame::Type type);
393
Steve Blockd0582a62009-12-15 09:54:21 +0000394 void EnterExitFramePrologue(ExitFrame::Mode mode);
395 void EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc);
396
Steve Blocka7e24c12009-10-30 11:49:00 +0000397 // Allocation support helpers.
398 void LoadAllocationTopHelper(Register result,
399 Register result_end,
400 Register scratch,
401 AllocationFlags flags);
402 void UpdateAllocationTopHelper(Register result_end, Register scratch);
403};
404
405
406// The code patcher is used to patch (typically) small parts of code e.g. for
407// debugging and other types of instrumentation. When using the code patcher
408// the exact number of bytes specified must be emitted. Is not legal to emit
409// relocation information. If any of these constraints are violated it causes
410// an assertion.
411class CodePatcher {
412 public:
413 CodePatcher(byte* address, int size);
414 virtual ~CodePatcher();
415
416 // Macro assembler to emit code.
417 MacroAssembler* masm() { return &masm_; }
418
419 private:
420 byte* address_; // The address of the code being patched.
421 int size_; // Number of bytes of the expected patch size.
422 MacroAssembler masm_; // Macro assembler used to generate the code.
423};
424
425
426// -----------------------------------------------------------------------------
427// Static helper functions.
428
429// Generate an Operand for loading a field from an object.
430static inline Operand FieldOperand(Register object, int offset) {
431 return Operand(object, offset - kHeapObjectTag);
432}
433
434
435// Generate an Operand for loading an indexed field from an object.
436static inline Operand FieldOperand(Register object,
437 Register index,
438 ScaleFactor scale,
439 int offset) {
440 return Operand(object, index, scale, offset - kHeapObjectTag);
441}
442
443
444#ifdef GENERATED_CODE_COVERAGE
445extern void LogGeneratedCodeCoverage(const char* file_line);
446#define CODE_COVERAGE_STRINGIFY(x) #x
447#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
448#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
449#define ACCESS_MASM(masm) { \
450 byte* ia32_coverage_function = \
451 reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \
452 masm->pushfd(); \
453 masm->pushad(); \
454 masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__))); \
455 masm->call(ia32_coverage_function, RelocInfo::RUNTIME_ENTRY); \
456 masm->pop(eax); \
457 masm->popad(); \
458 masm->popfd(); \
459 } \
460 masm->
461#else
462#define ACCESS_MASM(masm) masm->
463#endif
464
465
466} } // namespace v8::internal
467
468#endif // V8_IA32_MACRO_ASSEMBLER_IA32_H_