macro-assembler-ia32.h revision 589d6979ff2ef66fca2d8fa51404c369ca5e9250
18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 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"
32257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "v8globals.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen// Flags used for the AllocateInNewSpace functions.
3825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsenenum AllocationFlags {
3925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // No special flags.
4025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  NO_ALLOCATION_FLAGS = 0,
4125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // Return the pointer to the allocated already tagged as a heap object.
4225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  TAG_OBJECT = 1 << 0,
4325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // The content of the result register already contains the allocation top in
4425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  // new space.
4525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen  RESULT_CONTAINS_TOP = 1 << 1
4625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen};
4725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen
48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
49e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Convenience for platform-independent signatures.  We do not normally
50e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// distinguish memory operands from other operands on ia32.
51e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarketypedef Operand MemOperand;
52e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// MacroAssembler implements a collection of frequently used macros.
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MacroAssembler: public Assembler {
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // The isolate parameter can be NULL if the macro assembler should
578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // not use isolate-dependent functionality. In this case, it's the
588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // responsibility of the caller to never invoke such function on the
598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // macro assembler.
608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler(Isolate* isolate, void* buffer, int size);
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // GC Support
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // For page containing |object| mark region covering |addr| dirty.
667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // RecordWriteHelper only works if the object is not in new
676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // space.
686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void RecordWriteHelper(Register object,
696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         Register addr,
706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                         Register scratch);
716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check if object is in new space.
736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // scratch can be object itself, but it will be clobbered.
746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void InNewSpace(Register object,
756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  Register scratch,
766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                  Condition cc,  // equal for new space, not_equal otherwise.
77257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  Label* branch,
78257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  Label::Distance branch_near = Label::kFar);
796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
808defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // For page containing |object| mark region covering [object+offset]
818defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // dirty. |object| is the object being stored into, |value| is the
828defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // object being stored. If offset is zero, then the scratch register
838defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // contains the array index into the elements array represented as a
848defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // Smi. All registers are clobbered by the operation. RecordWrite
858defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // filters out smis so it does not update the write barrier if the
868defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // value is a smi.
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordWrite(Register object,
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   int offset,
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   Register value,
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   Register scratch);
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
928defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // For page containing |object| mark region covering |address|
938defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // dirty. |object| is the object being stored into, |value| is the
948defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // object being stored. All registers are clobbered by the
958defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // operation. RecordWrite filters out smis so it does not update the
968defd9ff6930b4e24729971a61cf7469daf119beSteve Block  // write barrier if the value is a smi.
978defd9ff6930b4e24729971a61cf7469daf119beSteve Block  void RecordWrite(Register object,
988defd9ff6930b4e24729971a61cf7469daf119beSteve Block                   Register address,
998defd9ff6930b4e24729971a61cf7469daf119beSteve Block                   Register value);
1008defd9ff6930b4e24729971a61cf7469daf119beSteve Block
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugger Support
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
105402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void DebugBreak();
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Activation frames
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Enter specific kind of exit frame. Expects the number of
118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // arguments in register eax and sets up the number of arguments in
119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // register edi and the pointer to the first argument in register
120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // esi.
121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void EnterExitFrame(bool save_doubles);
122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
1238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  void EnterApiExitFrame(int argc);
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Leave the current exit frame. Expects the return value in
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // register eax:edx (untouched) and the pointer to the first
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // argument in register esi.
128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void LeaveExitFrame(bool save_doubles);
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Leave the current exit frame. Expects the return value in
1318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // register eax (untouched).
1328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  void LeaveApiExitFrame();
1338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Find the function context up the context chain.
135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void LoadContext(Register dst, int context_chain_length);
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load the global function with the given index.
13880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void LoadGlobalFunction(int index, Register function);
13980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
14080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Load the initial map from the global function. The registers
14180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // function and map can be the same.
14280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void LoadGlobalFunctionInitialMap(Register function, Register map);
14380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Push and pop the registers that can hold pointers.
145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PushSafepointRegisters() { pushad(); }
146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void PopSafepointRegisters() { popad(); }
147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Store the value in register/immediate src in the safepoint
148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // register stack slot for register dst.
149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void StoreToSafepointRegisterSlot(Register dst, Register src);
150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void StoreToSafepointRegisterSlot(Register dst, Immediate src);
151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void LoadFromSafepointRegisterSlot(Register dst, Register src);
152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // JavaScript invokes
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Setup call kind marking in ecx. The method takes ecx as an
157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // explicit first parameter to make the code more readable at the
158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // call sites.
159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void SetCallKind(Register dst, CallKind kind);
160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the JavaScript function code by either calling or jumping.
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeCode(const Operand& code,
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& expected,
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& actual,
165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                  InvokeFlag flag,
166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  const CallWrapper& call_wrapper,
167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  CallKind call_kind);
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeCode(Handle<Code> code,
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& expected,
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  const ParameterCount& actual,
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  RelocInfo::Mode rmode,
173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                  InvokeFlag flag,
174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  const CallWrapper& call_wrapper,
175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                  CallKind call_kind);
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke the JavaScript function in the given register. Changes the
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // current context to the context in the function before invoking.
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokeFunction(Register function,
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const ParameterCount& actual,
181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      InvokeFlag flag,
182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      const CallWrapper& call_wrapper,
183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      CallKind call_kind);
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
185402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void InvokeFunction(JSFunction* function,
186402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                      const ParameterCount& actual,
187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      InvokeFlag flag,
188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      const CallWrapper& call_wrapper,
189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      CallKind call_kind);
190402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Invoke specified builtin JavaScript function. Adds an entry to
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the unresolved list if the name does not resolve.
193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void InvokeBuiltin(Builtins::JavaScript id,
194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                     InvokeFlag flag,
195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                     const CallWrapper& call_wrapper = NullCallWrapper());
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
197791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  // Store the function for the given builtin in the target register.
198791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block  void GetBuiltinFunction(Register target, Builtins::JavaScript id);
199791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Store the code object for the given builtin in the target register.
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void GetBuiltinEntry(Register target, Builtins::JavaScript id);
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Expression support
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Set(Register dst, const Immediate& x);
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Set(const Operand& dst, const Immediate& x);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
207053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  // Support for constant splitting.
208053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  bool IsUnsafeImmediate(const Immediate& x);
209053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  void SafeSet(Register dst, const Immediate& x);
210053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block  void SafePush(const Immediate& x);
211053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block
21269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Compare a register against a known root, e.g. undefined, null, true, ...
21369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void CompareRoot(Register with, Heap::RootListIndex index);
21469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare object type for heap object.
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Incoming register is heap_object and outgoing register is map.
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CmpObjectType(Register heap_object, InstanceType type, Register map);
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compare instance type for map.
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CmpInstanceType(Register map, InstanceType type);
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Check if a map for a JSObject indicates that the object has fast elements.
2233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Jump to the specified label if it does not.
2243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void CheckFastElements(Register map,
2253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         Label* fail,
2263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         Label::Distance distance = Label::kFar);
2273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check if the map of an object is equal to a specified map and branch to
229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // label if not. Skip the smi check if not required (object is known to be a
230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // heap object)
2313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  void CheckMap(Register obj,
2323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Handle<Map> map,
2333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu                Label* fail,
234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                SmiCheckType smi_check_type);
235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Check if the map of an object is equal to a specified map and branch to a
237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // specified target if equal. Skip the smi check if not required (object is
238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // known to be a heap object)
239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void DispatchMap(Register obj,
240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   Handle<Map> map,
241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   Handle<Code> success,
242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                   SmiCheckType smi_check_type);
2433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu
244e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Check if the object in register heap_object is a string. Afterwards the
245e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // register map contains the object map and the register instance_type
246e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // contains the instance_type. The registers map and instance_type can be the
247e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // same in which case it contains the instance type afterwards. Either of the
248e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // registers map and instance_type can be the same as heap_object.
249e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Condition IsObjectStringType(Register heap_object,
250e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               Register map,
251e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke                               Register instance_type);
252e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check if a heap object's type is in the JSObject range, not including
2547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // JSFunction.  The object's map will be loaded in the map register.
2557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Any or all of the three registers may be the same.
2567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // The contents of the scratch register will always be overwritten.
2577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void IsObjectJSObjectType(Register heap_object,
2587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                            Register map,
2597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                            Register scratch,
2607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                            Label* fail);
2617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // The contents of the scratch register will be overwritten.
2637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  void IsInstanceJSObjectType(Register map, Register scratch, Label* fail);
2647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // FCmp is similar to integer cmp, but requires unsigned
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void FCmp();
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void ClampUint8(Register reg);
270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void ClampDoubleToUint8(XMMRegister input_reg,
272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          XMMRegister scratch_reg,
273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                          Register result_reg);
274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
276e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Smi tagging support.
277e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void SmiTag(Register reg) {
27869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
27969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    STATIC_ASSERT(kSmiTagSize == 1);
2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    add(reg, Operand(reg));
281e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
282e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void SmiUntag(Register reg) {
283e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    sar(reg, kSmiTagSize);
284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
285e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
286756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Modifies the register even if it does not contain a Smi!
287756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void SmiUntag(Register reg, Label* is_smi) {
28869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    STATIC_ASSERT(kSmiTagSize == 1);
289756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    sar(reg, kSmiTagSize);
29069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    STATIC_ASSERT(kSmiTag == 0);
291756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick    j(not_carry, is_smi);
292756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  }
293756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
2941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Jump the register contains a smi.
2953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  inline void JumpIfSmi(Register value,
2963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        Label* smi_label,
2973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        Label::Distance distance = Label::kFar) {
2983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    test(value, Immediate(kSmiTagMask));
2993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(zero, smi_label, distance);
3003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
3013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Jump if the operand is a smi.
3023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  inline void JumpIfSmi(Operand value,
3033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        Label* smi_label,
3043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                        Label::Distance distance = Label::kFar) {
3051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    test(value, Immediate(kSmiTagMask));
3063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(zero, smi_label, distance);
3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Jump if register contain a non-smi.
3093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  inline void JumpIfNotSmi(Register value,
3103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           Label* not_smi_label,
3113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                           Label::Distance distance = Label::kFar) {
3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    test(value, Immediate(kSmiTagMask));
3133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    j(not_zero, not_smi_label, distance);
3141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
3151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void LoadInstanceDescriptors(Register map, Register descriptors);
317756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
3180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void LoadPowerOf2(XMMRegister dst, Register scratch, int power);
3190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
320402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Abort execution if argument is not a number. Used in debug code.
3216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void AbortIfNotNumber(Register object);
3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Abort execution if argument is not a smi. Used in debug code.
3246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void AbortIfNotSmi(Register object);
325402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
326756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  // Abort execution if argument is a smi. Used in debug code.
327756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void AbortIfSmi(Register object);
328756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
32980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Abort execution if argument is a string. Used in debug code.
33080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void AbortIfNotString(Register object);
33180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Exception handling
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Push a new try handler and link into try handler chain.  The return
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // address must be pushed before calling this helper.
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void PushTryHandler(CodeLocation try_location, HandlerType type);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
339e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Unlink the stack handler on top of the stack from the try handler chain.
340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void PopTryHandler();
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Activate the top handler in the try hander chain.
343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void Throw(Register value);
344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  void ThrowUncatchable(UncatchableExceptionType type, Register value);
346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Inline caching support
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generate code for checking access rights - used for security checks
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // on access to global objects across environments. The holder register
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is left untouched, but the scratch register is clobbered.
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CheckAccessGlobalProxy(Register holder_reg,
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Register scratch,
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Label* miss);
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void LoadFromNumberDictionary(Label* miss,
3593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register elements,
3603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register key,
3613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register r0,
3623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register r1,
3633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register r2,
3643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                Register result);
3653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocation support
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate an object in new space. If the new space is exhausted control
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // continues at the gc_required label. The allocated object is returned in
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // result and end of the new object is returned in result_end. The register
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // scratch can be passed as no_reg in which case an additional object
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // reference will be added to the reloc info. The returned pointers in result
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and result_end have not yet been tagged as heap objects. If
376d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // result_contains_top_on_entry is true the content of result is known to be
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the allocation top on entry (could be result_end from a previous call to
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // AllocateInNewSpace). If result_contains_top_on_entry is true scratch
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // should be no_reg as it is never used.
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AllocateInNewSpace(int object_size,
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result,
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result_end,
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register scratch,
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Label* gc_required,
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          AllocationFlags flags);
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AllocateInNewSpace(int header_size,
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          ScaleFactor element_size,
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register element_count,
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result,
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result_end,
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register scratch,
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Label* gc_required,
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          AllocationFlags flags);
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AllocateInNewSpace(Register object_size,
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result,
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register result_end,
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Register scratch,
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          Label* gc_required,
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                          AllocationFlags flags);
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Undo allocation in new space. The object passed and objects allocated after
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // it will no longer be allocated. Make sure that no pointers are left to the
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object(s) no longer allocated as they would be invalid when allocation is
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // un-done.
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UndoAllocationInNewSpace(Register object);
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Allocate a heap number in new space with undefined value. The
4103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // register scratch2 can be passed as no_reg; the others must be
4113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // valid registers. Returns tagged pointer in result register, or
4123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // jumps to gc_required if new space is full.
4133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  void AllocateHeapNumber(Register result,
4143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                          Register scratch1,
4153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                          Register scratch2,
4163ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block                          Label* gc_required);
4173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
418d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate a sequential string. All the header fields of the string object
419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // are initialized.
420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void AllocateTwoByteString(Register result,
421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                             Register length,
422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                             Register scratch1,
423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                             Register scratch2,
424d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                             Register scratch3,
425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                             Label* gc_required);
426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void AllocateAsciiString(Register result,
427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Register length,
428d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Register scratch1,
429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Register scratch2,
430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Register scratch3,
431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                           Label* gc_required);
4329ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick  void AllocateAsciiString(Register result,
4339ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                           int length,
4349ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                           Register scratch1,
4359ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                           Register scratch2,
4369ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick                           Label* gc_required);
437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // Allocate a raw cons string object. Only the map field of the result is
439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  // initialized.
440589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void AllocateTwoByteConsString(Register result,
441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Register scratch1,
442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Register scratch2,
443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                          Label* gc_required);
444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void AllocateAsciiConsString(Register result,
445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                               Register scratch1,
446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                               Register scratch2,
447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block                               Label* gc_required);
448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
44969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Allocate a raw sliced string object. Only the map field of the result is
45069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // initialized.
451589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void AllocateTwoByteSlicedString(Register result,
45269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                            Register scratch1,
45369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                            Register scratch2,
45469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                            Label* gc_required);
45569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void AllocateAsciiSlicedString(Register result,
45669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                 Register scratch1,
45769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                 Register scratch2,
45869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                 Label* gc_required);
45969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
460b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Copy memory, byte-by-byte, from source to destination.  Not optimized for
461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // long or aligned copies.
462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // The contents of index and scratch are destroyed.
463b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  void CopyBytes(Register source,
464b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                 Register destination,
465b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                 Register length,
466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                 Register scratch);
4678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Support functions.
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if result is zero and op is negative.
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void NegativeZeroTest(Register result, Register op, Label* then_label);
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if result is zero and any of op1 and op2 are negative.
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Register scratch is destroyed, and it must be different from op2.
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void NegativeZeroTest(Register result, Register op1, Register op2,
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        Register scratch, Label* then_label);
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Try to get function prototype of a function and puts the value in
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the result register. Checks that the function really is a
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function and jumps to the miss label if the fast checks fail. The
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function register will be untouched; the other registers may be
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // clobbered.
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void TryGetFunctionPrototype(Register function,
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Register result,
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Register scratch,
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Label* miss);
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Generates code for reporting that an illegal operation has
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // occurred.
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void IllegalOperation(int num_arguments);
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Picks out an array index from the hash field.
49480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Register use:
49580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //   hash - holds the index's hash. Clobbered.
49680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  //   index - holds the overwritten index on exit.
49780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void IndexFromHash(Register hash, Register index);
49880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Runtime calls
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call a code stub.  Generate the code if necessary.
503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  void CallStub(CodeStub* stub, unsigned ast_id = kNoASTId);
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
505e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Call a code stub and return the code object called.  Try to generate
506e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // the code if necessary.  Do not perform a GC but instead return a retry
507e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // after GC failure.
5085913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* TryCallStub(CodeStub* stub);
509e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
510e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Tail call a code stub (jump).  Generate the code if necessary.
511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  void TailCallStub(CodeStub* stub);
512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
513e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Tail call a code stub (jump) and return the code object called.  Try to
514e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // generate the code if necessary.  Do not perform a GC but instead return
515e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // a retry after GC failure.
5165913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* TryTailCallStub(CodeStub* stub);
517e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return from a code stub after popping its arguments.
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void StubReturn(int argc);
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Call a runtime routine.
52244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CallRuntime(const Runtime::Function* f, int num_arguments);
523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void CallRuntimeSaveDoubles(Runtime::FunctionId id);
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5254515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Call a runtime function, returning the CodeStub object called.
526e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Try to generate the stub code if necessary.  Do not perform a GC
527e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // but instead return a retry after GC failure.
52844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MUST_USE_RESULT MaybeObject* TryCallRuntime(const Runtime::Function* f,
5295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                              int num_arguments);
530e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Convenience function: Same as above, but takes the fid instead.
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CallRuntime(Runtime::FunctionId id, int num_arguments);
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
534e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Convenience function: Same as above, but takes the fid instead.
5355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* TryCallRuntime(Runtime::FunctionId id,
5365913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                              int num_arguments);
537e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
538bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Convenience function: call an external reference.
539bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  void CallExternalReference(ExternalReference ref, int num_arguments);
540bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tail call of a runtime routine (jump).
5426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Like JumpToExternalReference, but also takes care of passing the number
5436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // of parameters.
5446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void TailCallExternalReference(const ExternalReference& ext,
5456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 int num_arguments,
5466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                 int result_size);
5476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5488a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Tail call of a runtime routine (jump). Try to generate the code if
5498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // necessary. Do not perform a GC but instead return a retry after GC failure.
5508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  MUST_USE_RESULT MaybeObject* TryTailCallExternalReference(
5518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      const ExternalReference& ext, int num_arguments, int result_size);
5528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Convenience function: tail call a runtime routine (jump).
5546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void TailCallRuntime(Runtime::FunctionId fid,
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       int num_arguments,
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                       int result_size);
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Convenience function: tail call a runtime routine (jump). Try to generate
5598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // the code if necessary. Do not perform a GC but instead return a retry after
5608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // GC failure.
5618a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  MUST_USE_RESULT MaybeObject* TryTailCallRuntime(Runtime::FunctionId fid,
5628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                                  int num_arguments,
5638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                                  int result_size);
5648a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Before calling a C-function from generated code, align arguments on stack.
5666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // After aligning the frame, arguments must be stored in esp[0], esp[4],
5676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // etc., not pushed. The argument count assumes all arguments are word sized.
5686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Some compilers/platforms require the stack to be aligned when calling
5696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // C++ code.
5706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Needs a scratch register to do some arithmetic. This register will be
5716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // trashed.
5726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void PrepareCallCFunction(int num_arguments, Register scratch);
5736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Calls a C function and cleans up the space for arguments allocated
5756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // by PrepareCallCFunction. The called function is not allowed to trigger a
5766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // garbage collection, since that might move the code and invalidate the
5776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // return address (unless this is somehow accounted for by the called
5786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // function).
5796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CallCFunction(ExternalReference function, int num_arguments);
5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CallCFunction(Register function, int num_arguments);
5816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5825913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // Prepares stack to put arguments (aligns and so on). Reserves
5835913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // space for return value if needed (assumes the return value is a handle).
5843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1)
5853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // etc. Saves context (esi). If space was reserved for return value then
5863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // stores the pointer to the reserved slot into esi.
5873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void PrepareCallApiFunction(int argc);
588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
58990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // Calls an API function. Allocates HandleScope, extracts
5905913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  // returned value from handle and propagates exceptions.
5918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Clobbers ebx, edi and caller-save registers. Restores context.
5928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // On return removes stack_space * kPointerSize (GCed).
5938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function,
5948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang                                           int stack_space);
595e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Jump to a runtime routine.
5976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void JumpToExternalReference(const ExternalReference& ext);
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  MaybeObject* TryJumpToExternalReference(const ExternalReference& ext);
6008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Utilities
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Ret();
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Return and drop arguments from stack, where the number of arguments
6081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // may be bigger than 2^16 - 1.  Requires a scratch register.
6091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void Ret(int bytes_dropped, Register scratch);
6101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Emit code to discard a non-negative number of pointer-sized elements
612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // from the stack, clobbering only the esp register.
613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Drop(int element_count);
614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Call(Label* target) { call(target); }
616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Emit call to the code we are currently generating.
618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void CallSelf() {
619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    call(self, RelocInfo::CODE_TARGET);
621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // Move if the registers are not identical.
6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  void Move(Register target, Register source);
6250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  void Move(Register target, Handle<Object> value);
627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
6283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Push a handle value.
6293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void Push(Handle<Object> handle) { push(handle); }
6303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<Object> CodeObject() {
6328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    ASSERT(!code_object_.is_null());
6338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return code_object_;
6348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // StatsCounter support
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SetCounter(StatsCounter* counter, int value);
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void IncrementCounter(StatsCounter* counter, int value);
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void DecrementCounter(StatsCounter* counter, int value);
643d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void IncrementCounter(Condition cc, StatsCounter* counter, int value);
644d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void DecrementCounter(Condition cc, StatsCounter* counter, int value);
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ---------------------------------------------------------------------------
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Debugging
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Calls Abort(msg) if the condition cc is not satisfied.
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Use --debug_code to enable.
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Assert(Condition cc, const char* msg);
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
654756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  void AssertFastElements(Register elements);
655756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Like Assert(), but always enabled.
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Check(Condition cc, const char* msg);
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print a message to stdout and abort execution.
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Abort(const char* msg);
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Check that the stack is aligned.
6636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void CheckStackAlignment();
6646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify restrictions about code generated in stubs.
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_generating_stub(bool value) { generating_stub_ = value; }
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool generating_stub() { return generating_stub_; }
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool allow_stub_calls() { return allow_stub_calls_; }
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
671d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // ---------------------------------------------------------------------------
672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // String utilities.
673d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
674402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // Check whether the instance type represents a flat ascii string. Jump to the
675402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // label if not. If the instance type can be scratched specify same register
676402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  // for both instance type and scratch.
677402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type,
678402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu                                              Register scratch,
6796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                              Label* on_not_flat_ascii_string);
680402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
681d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Checks if both objects are sequential ASCII strings, and jumps to label
682d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // if either is not.
683d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void JumpIfNotBothSequentialAsciiStrings(Register object1,
684d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                           Register object2,
685d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                           Register scratch1,
686d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                           Register scratch2,
6876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block                                           Label* on_not_flat_ascii_strings);
688d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static int SafepointRegisterStackIndex(Register reg) {
6908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    return SafepointRegisterStackIndex(reg.code());
6918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
6928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool generating_stub_;
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool allow_stub_calls_;
6963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  // This handle will be patched with the code object on installation.
6973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Handle<Object> code_object_;
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Helper functions for generating invokes.
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void InvokePrologue(const ParameterCount& expected,
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const ParameterCount& actual,
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      Handle<Code> code_constant,
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      const Operand& code_operand,
704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      Label* done,
705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                      InvokeFlag flag,
706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      Label::Distance done_near = Label::kFar,
707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      const CallWrapper& call_wrapper = NullCallWrapper(),
708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch                      CallKind call_kind = CALL_AS_METHOD);
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Activation support.
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void EnterFrame(StackFrame::Type type);
712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void LeaveFrame(StackFrame::Type type);
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
71480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  void EnterExitFramePrologue();
715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  void EnterExitFrameEpilogue(int argc, bool save_doubles);
716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
7178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  void LeaveExitFrameEpilogue();
7188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocation support helpers.
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void LoadAllocationTopHelper(Register result,
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               Register scratch,
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               AllocationFlags flags);
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void UpdateAllocationTopHelper(Register result_end, Register scratch);
724e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
725e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Helper for PopHandleScope.  Allowed to perform a GC and returns
726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // NULL if gc_allowed.  Does not perform a GC if !gc_allowed, and
727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // possibly returns a failure object indicating an allocation failure.
7285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck  MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved,
7295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    Register scratch,
7305913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                                    bool gc_allowed);
731e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
732e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
733e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Compute memory operands for safepoint stack slots.
734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Operand SafepointRegisterSlot(Register reg);
735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  static int SafepointRegisterStackIndex(int reg_code);
736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Needs access to SafepointRegisterStackIndex for optimized frame
738e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // traversal.
739e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  friend class OptimizedFrame;
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The code patcher is used to patch (typically) small parts of code e.g. for
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// debugging and other types of instrumentation. When using the code patcher
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the exact number of bytes specified must be emitted. Is not legal to emit
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// relocation information. If any of these constraints are violated it causes
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// an assertion.
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CodePatcher {
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodePatcher(byte* address, int size);
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~CodePatcher();
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Macro assembler to emit code.
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MacroAssembler* masm() { return &masm_; }
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte* address_;  // The address of the code being patched.
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int size_;  // Number of bytes of the expected patch size.
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MacroAssembler masm_;  // Macro assembler used to generate the code.
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static helper functions.
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate an Operand for loading a field from an object.
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline Operand FieldOperand(Register object, int offset) {
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Operand(object, offset - kHeapObjectTag);
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate an Operand for loading an indexed field from an object.
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic inline Operand FieldOperand(Register object,
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Register index,
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   ScaleFactor scale,
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   int offset) {
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return Operand(object, index, scale, offset - kHeapObjectTag);
778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangstatic inline Operand ContextOperand(Register context, int index) {
7828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return Operand(context, Context::SlotOffset(index));
7838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
7848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangstatic inline Operand GlobalObjectOperand() {
7878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  return ContextOperand(esi, Context::GLOBAL_INDEX);
7888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang}
7898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
7915913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// Generates an Operand for saving parameters after PrepareCallApiFunction.
7925913587db4c6bab03d97bfe44b06289fd6d7270dJohn ReckOperand ApiParameterOperand(int index);
7935913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef GENERATED_CODE_COVERAGE
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockextern void LogGeneratedCodeCoverage(const char* file_line);
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_STRINGIFY(x) #x
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) {                                               \
801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    byte* ia32_coverage_function =                                        \
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->pushfd();                                                       \
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->pushad();                                                       \
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__)));         \
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->call(ia32_coverage_function, RelocInfo::RUNTIME_ENTRY);         \
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->pop(eax);                                                       \
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->popad();                                                        \
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    masm->popfd();                                                        \
810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }                                                                       \
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  masm->
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define ACCESS_MASM(masm) masm->
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_IA32_MACRO_ASSEMBLER_IA32_H_
820