macro-assembler-ia32.h revision 6ded16be15dd865a9b21ea304d5273c8be299c87
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2009 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_IA32_MACRO_ASSEMBLER_IA32_H_
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_IA32_MACRO_ASSEMBLER_IA32_H_
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "assembler.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Convenience for platform-independent signatures.  We do not normally
37e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// distinguish memory operands from other operands on ia32.
38e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarketypedef Operand MemOperand;
39e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Forward declaration.
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass JumpTarget;
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implements a collection of frequently used macros.
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MacroAssembler: public Assembler {
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MacroAssembler(void* buffer, int size);
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // GC Support
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set the remebered set bit for an address which points into an
526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // object. RecordWriteHelper only works if the object is not in new
536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // space.
546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void RecordWriteHelper(Register object,
556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         Register addr,
566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         Register scratch);
576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check if object is in new space.
596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // scratch can be object itself, but it will be clobbered.
606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void InNewSpace(Register object,
616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  Register scratch,
626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  Condition cc,  // equal for new space, not_equal otherwise.
636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  Label* branch);
646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the remembered set bit for [object+offset].
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object is the object being stored into, value is the object being stored.
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If offset is zero, then the scratch register contains the array index into
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the elements array represented as a Smi.
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // All registers are clobbered by the operation.
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordWrite(Register object,
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   int offset,
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   Register value,
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   Register scratch);
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugger Support
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SaveRegistersToMemory(RegList regs);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RestoreRegistersFromMemory(RegList regs);
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PushRegistersFromMemory(RegList regs);
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PopRegistersToMemory(RegList regs);
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CopyRegistersFromStackToMemory(Register base,
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Register scratch,
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      RegList regs);
86402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void DebugBreak();
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
90d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Stack limit support
91d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
92d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Do simple test for stack overflow. This doesn't handle an overflow.
93d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void StackLimitCheck(Label* on_stack_limit_hit);
94d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
95d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // ---------------------------------------------------------------------------
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Activation frames
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
104d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Enter specific kind of exit frame; either in normal or debug mode.
105d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Expects the number of arguments in register eax and
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sets up the number of arguments in register edi and the pointer
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to the first argument in register esi.
108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void EnterExitFrame(ExitFrame::Mode mode);
109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
110d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void EnterApiExitFrame(ExitFrame::Mode mode, int stack_space, int argc);
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Leave the current exit frame. Expects the return value in
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register eax:edx (untouched) and the pointer to the first
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // argument in register esi.
115d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void LeaveExitFrame(ExitFrame::Mode mode);
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
117d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Find the function context up the context chain.
118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void LoadContext(Register dst, int context_chain_length);
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JavaScript invokes
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the JavaScript function code by either calling or jumping.
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeCode(const Operand& code,
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& expected,
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& actual,
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  InvokeFlag flag);
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeCode(Handle<Code> code,
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& expected,
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& actual,
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  RelocInfo::Mode rmode,
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  InvokeFlag flag);
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the JavaScript function in the given register. Changes the
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // current context to the context in the function before invoking.
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeFunction(Register function,
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const ParameterCount& actual,
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      InvokeFlag flag);
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void InvokeFunction(JSFunction* function,
142402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                      const ParameterCount& actual,
143402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                      InvokeFlag flag);
144402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke specified builtin JavaScript function. Adds an entry to
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the unresolved list if the name does not resolve.
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the code object for the given builtin in the target register.
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void GetBuiltinEntry(Register target, Builtins::JavaScript id);
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Expression support
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Set(Register dst, const Immediate& x);
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Set(const Operand& dst, const Immediate& x);
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare object type for heap object.
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Incoming register is heap_object and outgoing register is map.
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CmpObjectType(Register heap_object, InstanceType type, Register map);
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare instance type for map.
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CmpInstanceType(Register map, InstanceType type);
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // Check if the map of an object is equal to a specified map and
1643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // branch to label if not. Skip the smi check if not required
1653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // (object is known to be a heap object)
1663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void CheckMap(Register obj,
1673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Handle<Map> map,
1683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Label* fail,
1693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                bool is_heap_object);
1703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
171e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check if the object in register heap_object is a string. Afterwards the
172e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // register map contains the object map and the register instance_type
173e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // contains the instance_type. The registers map and instance_type can be the
174e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // same in which case it contains the instance type afterwards. Either of the
175e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // registers map and instance_type can be the same as heap_object.
176e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Condition IsObjectStringType(Register heap_object,
177e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               Register map,
178e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               Register instance_type);
179e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // FCmp is similar to integer cmp, but requires unsigned
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void FCmp();
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Smi tagging support.
185e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void SmiTag(Register reg) {
186e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    ASSERT(kSmiTag == 0);
1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    ASSERT(kSmiTagSize == 1);
1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    add(reg, Operand(reg));
189e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
190e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void SmiUntag(Register reg) {
191e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    sar(reg, kSmiTagSize);
192e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
193e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
194402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Abort execution if argument is not a number. Used in debug code.
1956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void AbortIfNotNumber(Register object);
1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Abort execution if argument is not a smi. Used in debug code.
1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void AbortIfNotSmi(Register object);
199402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exception handling
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push a new try handler and link into try handler chain.  The return
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // address must be pushed before calling this helper.
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PushTryHandler(CodeLocation try_location, HandlerType type);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
207e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Unlink the stack handler on top of the stack from the try handler chain.
208e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void PopTryHandler();
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Inline caching support
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generates code that verifies that the maps of objects in the
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // prototype chain of object hasn't changed since the code was
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // generated and branches to the miss label if any map has. If
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // necessary the function also generates code for security check
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in case of global object holders. The scratch and holder
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // registers are always clobbered, but the object register is only
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // clobbered if it the same as the holder register. The function
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // returns a register containing the holder - either object_reg or
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // holder_reg.
222402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // The function can optionally (when save_at_depth !=
223402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // kInvalidProtoDepth) save the object at the given depth by moving
224402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // it to [esp + kPointerSize].
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Register CheckMaps(JSObject* object, Register object_reg,
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     JSObject* holder, Register holder_reg,
227402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                     Register scratch,
228402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                     int save_at_depth,
229402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                     Label* miss);
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generate code for checking access rights - used for security checks
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // on access to global objects across environments. The holder register
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is left untouched, but the scratch register is clobbered.
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CheckAccessGlobalProxy(Register holder_reg,
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register scratch,
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Label* miss);
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocation support
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate an object in new space. If the new space is exhausted control
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // continues at the gc_required label. The allocated object is returned in
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result and end of the new object is returned in result_end. The register
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch can be passed as no_reg in which case an additional object
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // reference will be added to the reloc info. The returned pointers in result
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and result_end have not yet been tagged as heap objects. If
248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // result_contains_top_on_entry is true the content of result is known to be
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the allocation top on entry (could be result_end from a previous call to
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // AllocateInNewSpace). If result_contains_top_on_entry is true scratch
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should be no_reg as it is never used.
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AllocateInNewSpace(int object_size,
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result,
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result_end,
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register scratch,
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Label* gc_required,
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          AllocationFlags flags);
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AllocateInNewSpace(int header_size,
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          ScaleFactor element_size,
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register element_count,
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result,
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result_end,
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register scratch,
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Label* gc_required,
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          AllocationFlags flags);
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AllocateInNewSpace(Register object_size,
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result,
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result_end,
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register scratch,
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Label* gc_required,
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          AllocationFlags flags);
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Undo allocation in new space. The object passed and objects allocated after
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // it will no longer be allocated. Make sure that no pointers are left to the
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object(s) no longer allocated as they would be invalid when allocation is
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // un-done.
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UndoAllocationInNewSpace(Register object);
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate a heap number in new space with undefined value. The
2823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // register scratch2 can be passed as no_reg; the others must be
2833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // valid registers. Returns tagged pointer in result register, or
2843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // jumps to gc_required if new space is full.
2853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void AllocateHeapNumber(Register result,
2863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                          Register scratch1,
2873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                          Register scratch2,
2883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                          Label* gc_required);
2893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate a sequential string. All the header fields of the string object
291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // are initialized.
292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void AllocateTwoByteString(Register result,
293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                             Register length,
294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                             Register scratch1,
295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                             Register scratch2,
296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                             Register scratch3,
297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                             Label* gc_required);
298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void AllocateAsciiString(Register result,
299d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Register length,
300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Register scratch1,
301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Register scratch2,
302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Register scratch3,
303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Label* gc_required);
304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate a raw cons string object. Only the map field of the result is
306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // initialized.
307d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void AllocateConsString(Register result,
308d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Register scratch1,
309d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Register scratch2,
310d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Label* gc_required);
311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void AllocateAsciiConsString(Register result,
312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                               Register scratch1,
313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                               Register scratch2,
314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                               Label* gc_required);
315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Support functions.
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if result is zero and op is negative.
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void NegativeZeroTest(Register result, Register op, Label* then_label);
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if result is zero and op is negative in code using jump targets.
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void NegativeZeroTest(CodeGenerator* cgen,
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register result,
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register op,
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        JumpTarget* then_target);
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if result is zero and any of op1 and op2 are negative.
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register scratch is destroyed, and it must be different from op2.
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void NegativeZeroTest(Register result, Register op1, Register op2,
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register scratch, Label* then_label);
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Try to get function prototype of a function and puts the value in
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the result register. Checks that the function really is a
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function and jumps to the miss label if the fast checks fail. The
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function register will be untouched; the other registers may be
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // clobbered.
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void TryGetFunctionPrototype(Register function,
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Register result,
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Register scratch,
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Label* miss);
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generates code for reporting that an illegal operation has
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // occurred.
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void IllegalOperation(int num_arguments);
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Runtime calls
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call a code stub.  Generate the code if necessary.
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CallStub(CodeStub* stub);
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
353e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call a code stub and return the code object called.  Try to generate
354e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // the code if necessary.  Do not perform a GC but instead return a retry
355e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // after GC failure.
356e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Object* TryCallStub(CodeStub* stub);
357e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
358e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Tail call a code stub (jump).  Generate the code if necessary.
359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void TailCallStub(CodeStub* stub);
360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
361e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Tail call a code stub (jump) and return the code object called.  Try to
362e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // generate the code if necessary.  Do not perform a GC but instead return
363e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // a retry after GC failure.
364e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Object* TryTailCallStub(CodeStub* stub);
365e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return from a code stub after popping its arguments.
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void StubReturn(int argc);
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call a runtime routine.
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CallRuntime(Runtime::Function* f, int num_arguments);
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Call a runtime function, returning the CodeStub object called.
373e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Try to generate the stub code if necessary.  Do not perform a GC
374e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // but instead return a retry after GC failure.
375e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Object* TryCallRuntime(Runtime::Function* f, int num_arguments);
376e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convenience function: Same as above, but takes the fid instead.
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CallRuntime(Runtime::FunctionId id, int num_arguments);
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
380402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Convenience function: call an external reference.
381402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void CallExternalReference(ExternalReference ref, int num_arguments);
382402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convenience function: Same as above, but takes the fid instead.
384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Object* TryCallRuntime(Runtime::FunctionId id, int num_arguments);
385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tail call of a runtime routine (jump).
3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Like JumpToExternalReference, but also takes care of passing the number
3886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // of parameters.
3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void TailCallExternalReference(const ExternalReference& ext,
3906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 int num_arguments,
3916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 int result_size);
3926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Convenience function: tail call a runtime routine (jump).
3946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void TailCallRuntime(Runtime::FunctionId fid,
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       int num_arguments,
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       int result_size);
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Before calling a C-function from generated code, align arguments on stack.
3996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // After aligning the frame, arguments must be stored in esp[0], esp[4],
4006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // etc., not pushed. The argument count assumes all arguments are word sized.
4016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Some compilers/platforms require the stack to be aligned when calling
4026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // C++ code.
4036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Needs a scratch register to do some arithmetic. This register will be
4046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // trashed.
4056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void PrepareCallCFunction(int num_arguments, Register scratch);
4066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Calls a C function and cleans up the space for arguments allocated
4086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // by PrepareCallCFunction. The called function is not allowed to trigger a
4096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // garbage collection, since that might move the code and invalidate the
4106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // return address (unless this is somehow accounted for by the called
4116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // function).
4126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CallCFunction(ExternalReference function, int num_arguments);
4136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CallCFunction(Register function, int num_arguments);
4146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
415d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void PushHandleScope(Register scratch);
416d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
417d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Pops a handle scope using the specified scratch register and
418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // ensuring that saved register, it is not no_reg, is left unchanged.
419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void PopHandleScope(Register saved, Register scratch);
420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
421e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // As PopHandleScope, but does not perform a GC.  Instead, returns a
422e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // retry after GC failure object if GC is necessary.
423e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Object* TryPopHandleScope(Register saved, Register scratch);
424e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to a runtime routine.
4266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void JumpToExternalReference(const ExternalReference& ext);
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Utilities
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Ret();
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
434e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit code to discard a non-negative number of pointer-sized elements
435e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // from the stack, clobbering only the esp register.
436e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Drop(int element_count);
437e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Call(Label* target) { call(target); }
439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
440e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Move(Register target, Handle<Object> value);
441e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> CodeObject() { return code_object_; }
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // StatsCounter support
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SetCounter(StatsCounter* counter, int value);
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void IncrementCounter(StatsCounter* counter, int value);
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void DecrementCounter(StatsCounter* counter, int value);
451d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void IncrementCounter(Condition cc, StatsCounter* counter, int value);
452d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void DecrementCounter(Condition cc, StatsCounter* counter, int value);
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugging
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calls Abort(msg) if the condition cc is not satisfied.
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use --debug_code to enable.
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Assert(Condition cc, const char* msg);
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Like Assert(), but always enabled.
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Check(Condition cc, const char* msg);
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print a message to stdout and abort execution.
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Abort(const char* msg);
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the stack is aligned.
4696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CheckStackAlignment();
4706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify restrictions about code generated in stubs.
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_generating_stub(bool value) { generating_stub_ = value; }
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool generating_stub() { return generating_stub_; }
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool allow_stub_calls() { return allow_stub_calls_; }
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
477d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // ---------------------------------------------------------------------------
478d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // String utilities.
479d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
480402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Check whether the instance type represents a flat ascii string. Jump to the
481402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // label if not. If the instance type can be scratched specify same register
482402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // for both instance type and scratch.
483402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type,
484402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                              Register scratch,
4856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                              Label* on_not_flat_ascii_string);
486402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
487d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Checks if both objects are sequential ASCII strings, and jumps to label
488d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // if either is not.
489d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void JumpIfNotBothSequentialAsciiStrings(Register object1,
490d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                           Register object2,
491d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                           Register scratch1,
492d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                           Register scratch2,
4936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           Label* on_not_flat_ascii_strings);
494d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool generating_stub_;
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool allow_stub_calls_;
4983100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // This handle will be patched with the code object on installation.
4993100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Handle<Object> code_object_;
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Helper functions for generating invokes.
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokePrologue(const ParameterCount& expected,
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const ParameterCount& actual,
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Handle<Code> code_constant,
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const Operand& code_operand,
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Label* done,
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      InvokeFlag flag);
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Activation support.
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void EnterFrame(StackFrame::Type type);
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void LeaveFrame(StackFrame::Type type);
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void EnterExitFramePrologue(ExitFrame::Mode mode);
514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc);
515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocation support helpers.
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void LoadAllocationTopHelper(Register result,
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Register result_end,
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Register scratch,
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               AllocationFlags flags);
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateAllocationTopHelper(Register result_end, Register scratch);
522e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
523e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Helper for PopHandleScope.  Allowed to perform a GC and returns
524e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // NULL if gc_allowed.  Does not perform a GC if !gc_allowed, and
525e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // possibly returns a failure object indicating an allocation failure.
526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Object* PopHandleScopeHelper(Register saved,
527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               Register scratch,
528e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               bool gc_allowed);
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugging and other types of instrumentation. When using the code patcher
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exact number of bytes specified must be emitted. Is not legal to emit
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// relocation information. If any of these constraints are violated it causes
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// an assertion.
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodePatcher {
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodePatcher(byte* address, int size);
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~CodePatcher();
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Macro assembler to emit code.
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MacroAssembler* masm() { return &masm_; }
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* address_;  // The address of the code being patched.
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size_;  // Number of bytes of the expected patch size.
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MacroAssembler masm_;  // Macro assembler used to generate the code.
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static helper functions.
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate an Operand for loading a field from an object.
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline Operand FieldOperand(Register object, int offset) {
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Operand(object, offset - kHeapObjectTag);
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate an Operand for loading an indexed field from an object.
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline Operand FieldOperand(Register object,
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register index,
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   ScaleFactor scale,
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   int offset) {
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Operand(object, index, scale, offset - kHeapObjectTag);
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef GENERATED_CODE_COVERAGE
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockextern void LogGeneratedCodeCoverage(const char* file_line);
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_STRINGIFY(x) #x
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) {                                               \
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* ia32_coverage_function =                                        \
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->pushfd();                                                       \
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->pushad();                                                       \
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__)));         \
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->call(ia32_coverage_function, RelocInfo::RUNTIME_ENTRY);         \
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->pop(eax);                                                       \
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->popad();                                                        \
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->popfd();                                                        \
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }                                                                       \
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  masm->
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm->
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_IA32_MACRO_ASSEMBLER_IA32_H_
595