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
33namespace v8 {
34namespace internal {
35
36// Convenience for platform-independent signatures.  We do not normally
37// distinguish memory operands from other operands on ia32.
38typedef Operand MemOperand;
39
40// Forward declaration.
41class JumpTarget;
42
43// MacroAssembler implements a collection of frequently used macros.
44class 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.
495class 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.
514static 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.
520static 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
529extern 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