blob: ee9d70d31087f9861e79d900f3e675febc520311 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2009 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_
29#define V8_ARM_MACRO_ASSEMBLER_ARM_H_
30
31#include "assembler.h"
32
33namespace v8 {
34namespace internal {
35
36
37// Give alias names to registers
38const Register cp = { 8 }; // JavaScript context pointer
39
40
41enum InvokeJSFlags {
42 CALL_JS,
43 JUMP_JS
44};
45
46
47// MacroAssembler implements a collection of frequently used macros.
48class MacroAssembler: public Assembler {
49 public:
50 MacroAssembler(void* buffer, int size);
51
52 // ---------------------------------------------------------------------------
53 // Low-level helpers for compiler
54
55 // Jump, Call, and Ret pseudo instructions implementing inter-working
56 private:
57 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
58 void Call(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
59 public:
60 void Jump(Register target, Condition cond = al);
61 void Jump(byte* target, RelocInfo::Mode rmode, Condition cond = al);
62 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
63 void Call(Register target, Condition cond = al);
64 void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
65 void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
66 void Ret(Condition cond = al);
67 // Jumps to the label at the index given by the Smi in "index".
68 void SmiJumpTable(Register index, Vector<Label*> targets);
69 // Load an object from the root table.
70 void LoadRoot(Register destination,
71 Heap::RootListIndex index,
72 Condition cond = al);
73
74 // Sets the remembered set bit for [address+offset], where address is the
75 // address of the heap object 'object'. The address must be in the first 8K
76 // of an allocated page. The 'scratch' register is used in the
77 // implementation and all 3 registers are clobbered by the operation, as
78 // well as the ip register.
79 void RecordWrite(Register object, Register offset, Register scratch);
80
81 // ---------------------------------------------------------------------------
82 // Activation frames
83
84 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
85 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
86
87 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
88 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
89
90 // Enter specific kind of exit frame; either EXIT or
91 // EXIT_DEBUG. Expects the number of arguments in register r0 and
92 // the builtin function to call in register r1. Exits with argc in
93 // r4, argv in r6, and and the builtin function to call in r5.
94 void EnterExitFrame(StackFrame::Type type);
95
96 // Leave the current exit frame. Expects the return value in r0.
97 void LeaveExitFrame(StackFrame::Type type);
98
99 // Align the stack by optionally pushing a Smi zero.
100 void AlignStack(int offset);
101
102 // ---------------------------------------------------------------------------
103 // JavaScript invokes
104
105 // Invoke the JavaScript function code by either calling or jumping.
106 void InvokeCode(Register code,
107 const ParameterCount& expected,
108 const ParameterCount& actual,
109 InvokeFlag flag);
110
111 void InvokeCode(Handle<Code> code,
112 const ParameterCount& expected,
113 const ParameterCount& actual,
114 RelocInfo::Mode rmode,
115 InvokeFlag flag);
116
117 // Invoke the JavaScript function in the given register. Changes the
118 // current context to the context in the function before invoking.
119 void InvokeFunction(Register function,
120 const ParameterCount& actual,
121 InvokeFlag flag);
122
123
124#ifdef ENABLE_DEBUGGER_SUPPORT
125 // ---------------------------------------------------------------------------
126 // Debugger Support
127
128 void SaveRegistersToMemory(RegList regs);
129 void RestoreRegistersFromMemory(RegList regs);
130 void CopyRegistersFromMemoryToStack(Register base, RegList regs);
131 void CopyRegistersFromStackToMemory(Register base,
132 Register scratch,
133 RegList regs);
134#endif
135
136 // ---------------------------------------------------------------------------
137 // Exception handling
138
139 // Push a new try handler and link into try handler chain.
140 // The return address must be passed in register lr.
141 // On exit, r0 contains TOS (code slot).
142 void PushTryHandler(CodeLocation try_location, HandlerType type);
143
144
145 // ---------------------------------------------------------------------------
146 // Inline caching support
147
148 // Generates code that verifies that the maps of objects in the
149 // prototype chain of object hasn't changed since the code was
150 // generated and branches to the miss label if any map has. If
151 // necessary the function also generates code for security check
152 // in case of global object holders. The scratch and holder
153 // registers are always clobbered, but the object register is only
154 // clobbered if it the same as the holder register. The function
155 // returns a register containing the holder - either object_reg or
156 // holder_reg.
157 Register CheckMaps(JSObject* object, Register object_reg,
158 JSObject* holder, Register holder_reg,
159 Register scratch, Label* miss);
160
161 // Generate code for checking access rights - used for security checks
162 // on access to global objects across environments. The holder register
163 // is left untouched, whereas both scratch registers are clobbered.
164 void CheckAccessGlobalProxy(Register holder_reg,
165 Register scratch,
166 Label* miss);
167
168
169 // ---------------------------------------------------------------------------
170 // Allocation support
171
172 // Allocate an object in new space. The object_size is specified in words (not
173 // bytes). If the new space is exhausted control continues at the gc_required
174 // label. The allocated object is returned in result. If the flag
175 // tag_allocated_object is true the result is tagged as as a heap object.
176 void AllocateInNewSpace(int object_size,
177 Register result,
178 Register scratch1,
179 Register scratch2,
180 Label* gc_required,
181 AllocationFlags flags);
182 void AllocateInNewSpace(Register object_size,
183 Register result,
184 Register scratch1,
185 Register scratch2,
186 Label* gc_required,
187 AllocationFlags flags);
188
189 // Undo allocation in new space. The object passed and objects allocated after
190 // it will no longer be allocated. The caller must make sure that no pointers
191 // are left to the object(s) no longer allocated as they would be invalid when
192 // allocation is undone.
193 void UndoAllocationInNewSpace(Register object, Register scratch);
194
195 // ---------------------------------------------------------------------------
196 // Support functions.
197
198 // Try to get function prototype of a function and puts the value in
199 // the result register. Checks that the function really is a
200 // function and jumps to the miss label if the fast checks fail. The
201 // function register will be untouched; the other registers may be
202 // clobbered.
203 void TryGetFunctionPrototype(Register function,
204 Register result,
205 Register scratch,
206 Label* miss);
207
208 // Compare object type for heap object. heap_object contains a non-Smi
209 // whose object type should be compared with the given type. This both
210 // sets the flags and leaves the object type in the type_reg register.
211 // It leaves the map in the map register (unless the type_reg and map register
212 // are the same register). It leaves the heap object in the heap_object
213 // register unless the heap_object register is the same register as one of the
214 // other registers.
215 void CompareObjectType(Register heap_object,
216 Register map,
217 Register type_reg,
218 InstanceType type);
219
220 // Compare instance type in a map. map contains a valid map object whose
221 // object type should be compared with the given type. This both
222 // sets the flags and leaves the object type in the type_reg register. It
223 // leaves the heap object in the heap_object register unless the heap_object
224 // register is the same register as type_reg.
225 void CompareInstanceType(Register map,
226 Register type_reg,
227 InstanceType type);
228
229 inline void BranchOnSmi(Register value, Label* smi_label) {
230 tst(value, Operand(kSmiTagMask));
231 b(eq, smi_label);
232 }
233
234 inline void BranchOnNotSmi(Register value, Label* not_smi_label) {
235 tst(value, Operand(kSmiTagMask));
236 b(ne, not_smi_label);
237 }
238
239 // Generates code for reporting that an illegal operation has
240 // occurred.
241 void IllegalOperation(int num_arguments);
242
243
244 // ---------------------------------------------------------------------------
245 // Runtime calls
246
247 // Call a code stub.
248 void CallStub(CodeStub* stub, Condition cond = al);
249 void CallJSExitStub(CodeStub* stub);
250
251 // Return from a code stub after popping its arguments.
252 void StubReturn(int argc);
253
254 // Call a runtime routine.
255 // Eventually this should be used for all C calls.
256 void CallRuntime(Runtime::Function* f, int num_arguments);
257
258 // Convenience function: Same as above, but takes the fid instead.
259 void CallRuntime(Runtime::FunctionId fid, int num_arguments);
260
261 // Tail call of a runtime routine (jump).
262 // Like JumpToRuntime, but also takes care of passing the number
263 // of parameters.
264 void TailCallRuntime(const ExternalReference& ext,
265 int num_arguments,
266 int result_size);
267
268 // Jump to a runtime routine.
269 void JumpToRuntime(const ExternalReference& builtin);
270
271 // Invoke specified builtin JavaScript function. Adds an entry to
272 // the unresolved list if the name does not resolve.
273 void InvokeBuiltin(Builtins::JavaScript id, InvokeJSFlags flags);
274
275 // Store the code object for the given builtin in the target register and
276 // setup the function in r1.
277 void GetBuiltinEntry(Register target, Builtins::JavaScript id);
278
279 struct Unresolved {
280 int pc;
281 uint32_t flags; // see Bootstrapper::FixupFlags decoders/encoders.
282 const char* name;
283 };
284 List<Unresolved>* unresolved() { return &unresolved_; }
285
286 Handle<Object> CodeObject() { return code_object_; }
287
288
289 // ---------------------------------------------------------------------------
290 // StatsCounter support
291
292 void SetCounter(StatsCounter* counter, int value,
293 Register scratch1, Register scratch2);
294 void IncrementCounter(StatsCounter* counter, int value,
295 Register scratch1, Register scratch2);
296 void DecrementCounter(StatsCounter* counter, int value,
297 Register scratch1, Register scratch2);
298
299
300 // ---------------------------------------------------------------------------
301 // Debugging
302
303 // Calls Abort(msg) if the condition cc is not satisfied.
304 // Use --debug_code to enable.
305 void Assert(Condition cc, const char* msg);
306
307 // Like Assert(), but always enabled.
308 void Check(Condition cc, const char* msg);
309
310 // Print a message to stdout and abort execution.
311 void Abort(const char* msg);
312
313 // Verify restrictions about code generated in stubs.
314 void set_generating_stub(bool value) { generating_stub_ = value; }
315 bool generating_stub() { return generating_stub_; }
316 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
317 bool allow_stub_calls() { return allow_stub_calls_; }
318
319 private:
320 List<Unresolved> unresolved_;
321 bool generating_stub_;
322 bool allow_stub_calls_;
323 Handle<Object> code_object_; // This handle will be patched with the code
324 // object on installation.
325
326 // Helper functions for generating invokes.
327 void InvokePrologue(const ParameterCount& expected,
328 const ParameterCount& actual,
329 Handle<Code> code_constant,
330 Register code_reg,
331 Label* done,
332 InvokeFlag flag);
333
334 // Prepares for a call or jump to a builtin by doing two things:
335 // 1. Emits code that fetches the builtin's function object from the context
336 // at runtime, and puts it in the register rdi.
337 // 2. Fetches the builtin's code object, and returns it in a handle, at
338 // compile time, so that later code can emit instructions to jump or call
339 // the builtin directly. If the code object has not yet been created, it
340 // returns the builtin code object for IllegalFunction, and sets the
341 // output parameter "resolved" to false. Code that uses the return value
342 // should then add the address and the builtin name to the list of fixups
343 // called unresolved_, which is fixed up by the bootstrapper.
344 Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
345
346 // Activation support.
347 void EnterFrame(StackFrame::Type type);
348 void LeaveFrame(StackFrame::Type type);
349};
350
351
352#ifdef ENABLE_DEBUGGER_SUPPORT
353// The code patcher is used to patch (typically) small parts of code e.g. for
354// debugging and other types of instrumentation. When using the code patcher
355// the exact number of bytes specified must be emitted. It is not legal to emit
356// relocation information. If any of these constraints are violated it causes
357// an assertion to fail.
358class CodePatcher {
359 public:
360 CodePatcher(byte* address, int instructions);
361 virtual ~CodePatcher();
362
363 // Macro assembler to emit code.
364 MacroAssembler* masm() { return &masm_; }
365
366 // Emit an instruction directly.
367 void Emit(Instr x);
368
369 // Emit an address directly.
370 void Emit(Address addr);
371
372 private:
373 byte* address_; // The address of the code being patched.
374 int instructions_; // Number of instructions of the expected patch size.
375 int size_; // Number of bytes of the expected patch size.
376 MacroAssembler masm_; // Macro assembler used to generate the code.
377};
378#endif // ENABLE_DEBUGGER_SUPPORT
379
380
381// -----------------------------------------------------------------------------
382// Static helper functions.
383
384// Generate a MemOperand for loading a field from an object.
385static inline MemOperand FieldMemOperand(Register object, int offset) {
386 return MemOperand(object, offset - kHeapObjectTag);
387}
388
389
390#ifdef GENERATED_CODE_COVERAGE
391#define CODE_COVERAGE_STRINGIFY(x) #x
392#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
393#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
394#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
395#else
396#define ACCESS_MASM(masm) masm->
397#endif
398
399
400} } // namespace v8::internal
401
402#endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_