blob: efc5bfae725db91c1b80db8c3c8c2d35623f6920 [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);
Leon Clarkee46be812010-01-19 14:06:41 +000067
68 // Emit code to discard a non-negative number of pointer-sized elements
69 // from the stack, clobbering only the sp register.
70 void Drop(int count, Condition cond = al);
71
72 void Call(Label* target);
73 void Move(Register dst, Handle<Object> value);
Steve Blocka7e24c12009-10-30 11:49:00 +000074 // Jumps to the label at the index given by the Smi in "index".
75 void SmiJumpTable(Register index, Vector<Label*> targets);
76 // Load an object from the root table.
77 void LoadRoot(Register destination,
78 Heap::RootListIndex index,
79 Condition cond = al);
80
81 // Sets the remembered set bit for [address+offset], where address is the
82 // address of the heap object 'object'. The address must be in the first 8K
83 // of an allocated page. The 'scratch' register is used in the
84 // implementation and all 3 registers are clobbered by the operation, as
85 // well as the ip register.
86 void RecordWrite(Register object, Register offset, Register scratch);
87
88 // ---------------------------------------------------------------------------
Steve Blockd0582a62009-12-15 09:54:21 +000089 // Stack limit support
90
91 void StackLimitCheck(Label* on_stack_limit_hit);
92
93 // ---------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +000094 // Activation frames
95
96 void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
97 void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
98
99 void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
100 void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
101
Steve Blockd0582a62009-12-15 09:54:21 +0000102 // Enter specific kind of exit frame; either normal or debug mode.
103 // Expects the number of arguments in register r0 and
Steve Blocka7e24c12009-10-30 11:49:00 +0000104 // the builtin function to call in register r1. Exits with argc in
105 // r4, argv in r6, and and the builtin function to call in r5.
Steve Blockd0582a62009-12-15 09:54:21 +0000106 void EnterExitFrame(ExitFrame::Mode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000107
108 // Leave the current exit frame. Expects the return value in r0.
Steve Blockd0582a62009-12-15 09:54:21 +0000109 void LeaveExitFrame(ExitFrame::Mode mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000110
111 // Align the stack by optionally pushing a Smi zero.
112 void AlignStack(int offset);
113
Steve Blockd0582a62009-12-15 09:54:21 +0000114 void LoadContext(Register dst, int context_chain_length);
115
Steve Blocka7e24c12009-10-30 11:49:00 +0000116 // ---------------------------------------------------------------------------
117 // JavaScript invokes
118
119 // Invoke the JavaScript function code by either calling or jumping.
120 void InvokeCode(Register code,
121 const ParameterCount& expected,
122 const ParameterCount& actual,
123 InvokeFlag flag);
124
125 void InvokeCode(Handle<Code> code,
126 const ParameterCount& expected,
127 const ParameterCount& actual,
128 RelocInfo::Mode rmode,
129 InvokeFlag flag);
130
131 // Invoke the JavaScript function in the given register. Changes the
132 // current context to the context in the function before invoking.
133 void InvokeFunction(Register function,
134 const ParameterCount& actual,
135 InvokeFlag flag);
136
137
138#ifdef ENABLE_DEBUGGER_SUPPORT
139 // ---------------------------------------------------------------------------
140 // Debugger Support
141
142 void SaveRegistersToMemory(RegList regs);
143 void RestoreRegistersFromMemory(RegList regs);
144 void CopyRegistersFromMemoryToStack(Register base, RegList regs);
145 void CopyRegistersFromStackToMemory(Register base,
146 Register scratch,
147 RegList regs);
148#endif
149
150 // ---------------------------------------------------------------------------
151 // Exception handling
152
153 // Push a new try handler and link into try handler chain.
154 // The return address must be passed in register lr.
155 // On exit, r0 contains TOS (code slot).
156 void PushTryHandler(CodeLocation try_location, HandlerType type);
157
Leon Clarkee46be812010-01-19 14:06:41 +0000158 // Unlink the stack handler on top of the stack from the try handler chain.
159 // Must preserve the result register.
160 void PopTryHandler();
Steve Blocka7e24c12009-10-30 11:49:00 +0000161
162 // ---------------------------------------------------------------------------
163 // Inline caching support
164
165 // Generates code that verifies that the maps of objects in the
166 // prototype chain of object hasn't changed since the code was
167 // generated and branches to the miss label if any map has. If
168 // necessary the function also generates code for security check
169 // in case of global object holders. The scratch and holder
170 // registers are always clobbered, but the object register is only
171 // clobbered if it the same as the holder register. The function
172 // returns a register containing the holder - either object_reg or
173 // holder_reg.
174 Register CheckMaps(JSObject* object, Register object_reg,
175 JSObject* holder, Register holder_reg,
176 Register scratch, Label* miss);
177
178 // Generate code for checking access rights - used for security checks
179 // on access to global objects across environments. The holder register
180 // is left untouched, whereas both scratch registers are clobbered.
181 void CheckAccessGlobalProxy(Register holder_reg,
182 Register scratch,
183 Label* miss);
184
185
186 // ---------------------------------------------------------------------------
187 // Allocation support
188
189 // Allocate an object in new space. The object_size is specified in words (not
190 // bytes). If the new space is exhausted control continues at the gc_required
191 // label. The allocated object is returned in result. If the flag
192 // tag_allocated_object is true the result is tagged as as a heap object.
193 void AllocateInNewSpace(int object_size,
194 Register result,
195 Register scratch1,
196 Register scratch2,
197 Label* gc_required,
198 AllocationFlags flags);
199 void AllocateInNewSpace(Register object_size,
200 Register result,
201 Register scratch1,
202 Register scratch2,
203 Label* gc_required,
204 AllocationFlags flags);
205
206 // Undo allocation in new space. The object passed and objects allocated after
207 // it will no longer be allocated. The caller must make sure that no pointers
208 // are left to the object(s) no longer allocated as they would be invalid when
209 // allocation is undone.
210 void UndoAllocationInNewSpace(Register object, Register scratch);
211
212 // ---------------------------------------------------------------------------
213 // Support functions.
214
215 // Try to get function prototype of a function and puts the value in
216 // the result register. Checks that the function really is a
217 // function and jumps to the miss label if the fast checks fail. The
218 // function register will be untouched; the other registers may be
219 // clobbered.
220 void TryGetFunctionPrototype(Register function,
221 Register result,
222 Register scratch,
223 Label* miss);
224
225 // Compare object type for heap object. heap_object contains a non-Smi
226 // whose object type should be compared with the given type. This both
227 // sets the flags and leaves the object type in the type_reg register.
228 // It leaves the map in the map register (unless the type_reg and map register
229 // are the same register). It leaves the heap object in the heap_object
230 // register unless the heap_object register is the same register as one of the
231 // other registers.
232 void CompareObjectType(Register heap_object,
233 Register map,
234 Register type_reg,
235 InstanceType type);
236
237 // Compare instance type in a map. map contains a valid map object whose
238 // object type should be compared with the given type. This both
239 // sets the flags and leaves the object type in the type_reg register. It
240 // leaves the heap object in the heap_object register unless the heap_object
241 // register is the same register as type_reg.
242 void CompareInstanceType(Register map,
243 Register type_reg,
244 InstanceType type);
245
246 inline void BranchOnSmi(Register value, Label* smi_label) {
247 tst(value, Operand(kSmiTagMask));
248 b(eq, smi_label);
249 }
250
251 inline void BranchOnNotSmi(Register value, Label* not_smi_label) {
252 tst(value, Operand(kSmiTagMask));
253 b(ne, not_smi_label);
254 }
255
256 // Generates code for reporting that an illegal operation has
257 // occurred.
258 void IllegalOperation(int num_arguments);
259
Steve Blockd0582a62009-12-15 09:54:21 +0000260 // Uses VFP instructions to Convert a Smi to a double.
261 void IntegerToDoubleConversionWithVFP3(Register inReg,
262 Register outHighReg,
263 Register outLowReg);
264
Steve Blocka7e24c12009-10-30 11:49:00 +0000265
266 // ---------------------------------------------------------------------------
267 // Runtime calls
268
269 // Call a code stub.
270 void CallStub(CodeStub* stub, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000271
272 // Return from a code stub after popping its arguments.
273 void StubReturn(int argc);
274
275 // Call a runtime routine.
276 // Eventually this should be used for all C calls.
277 void CallRuntime(Runtime::Function* f, int num_arguments);
278
279 // Convenience function: Same as above, but takes the fid instead.
280 void CallRuntime(Runtime::FunctionId fid, int num_arguments);
281
282 // Tail call of a runtime routine (jump).
283 // Like JumpToRuntime, but also takes care of passing the number
284 // of parameters.
285 void TailCallRuntime(const ExternalReference& ext,
286 int num_arguments,
287 int result_size);
288
289 // Jump to a runtime routine.
290 void JumpToRuntime(const ExternalReference& builtin);
291
292 // Invoke specified builtin JavaScript function. Adds an entry to
293 // the unresolved list if the name does not resolve.
294 void InvokeBuiltin(Builtins::JavaScript id, InvokeJSFlags flags);
295
296 // Store the code object for the given builtin in the target register and
297 // setup the function in r1.
298 void GetBuiltinEntry(Register target, Builtins::JavaScript id);
299
300 struct Unresolved {
301 int pc;
302 uint32_t flags; // see Bootstrapper::FixupFlags decoders/encoders.
303 const char* name;
304 };
305 List<Unresolved>* unresolved() { return &unresolved_; }
306
307 Handle<Object> CodeObject() { return code_object_; }
308
309
310 // ---------------------------------------------------------------------------
311 // StatsCounter support
312
313 void SetCounter(StatsCounter* counter, int value,
314 Register scratch1, Register scratch2);
315 void IncrementCounter(StatsCounter* counter, int value,
316 Register scratch1, Register scratch2);
317 void DecrementCounter(StatsCounter* counter, int value,
318 Register scratch1, Register scratch2);
319
320
321 // ---------------------------------------------------------------------------
322 // Debugging
323
324 // Calls Abort(msg) if the condition cc is not satisfied.
325 // Use --debug_code to enable.
326 void Assert(Condition cc, const char* msg);
327
328 // Like Assert(), but always enabled.
329 void Check(Condition cc, const char* msg);
330
331 // Print a message to stdout and abort execution.
332 void Abort(const char* msg);
333
334 // Verify restrictions about code generated in stubs.
335 void set_generating_stub(bool value) { generating_stub_ = value; }
336 bool generating_stub() { return generating_stub_; }
337 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
338 bool allow_stub_calls() { return allow_stub_calls_; }
339
Leon Clarked91b9f72010-01-27 17:25:45 +0000340 // ---------------------------------------------------------------------------
341 // String utilities
342
343 // Checks if both objects are sequential ASCII strings and jumps to label
344 // if either is not. Assumes that neither object is a smi.
345 void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
346 Register object2,
347 Register scratch1,
348 Register scratch2,
349 Label *failure);
350
351 // Checks if both objects are sequential ASCII strings and jumps to label
352 // if either is not.
353 void JumpIfNotBothSequentialAsciiStrings(Register first,
354 Register second,
355 Register scratch1,
356 Register scratch2,
357 Label* not_flat_ascii_strings);
358
Steve Blocka7e24c12009-10-30 11:49:00 +0000359 private:
360 List<Unresolved> unresolved_;
361 bool generating_stub_;
362 bool allow_stub_calls_;
363 Handle<Object> code_object_; // This handle will be patched with the code
364 // object on installation.
365
366 // Helper functions for generating invokes.
367 void InvokePrologue(const ParameterCount& expected,
368 const ParameterCount& actual,
369 Handle<Code> code_constant,
370 Register code_reg,
371 Label* done,
372 InvokeFlag flag);
373
374 // Prepares for a call or jump to a builtin by doing two things:
375 // 1. Emits code that fetches the builtin's function object from the context
376 // at runtime, and puts it in the register rdi.
377 // 2. Fetches the builtin's code object, and returns it in a handle, at
378 // compile time, so that later code can emit instructions to jump or call
379 // the builtin directly. If the code object has not yet been created, it
380 // returns the builtin code object for IllegalFunction, and sets the
381 // output parameter "resolved" to false. Code that uses the return value
382 // should then add the address and the builtin name to the list of fixups
383 // called unresolved_, which is fixed up by the bootstrapper.
384 Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
385
386 // Activation support.
387 void EnterFrame(StackFrame::Type type);
388 void LeaveFrame(StackFrame::Type type);
389};
390
391
392#ifdef ENABLE_DEBUGGER_SUPPORT
393// The code patcher is used to patch (typically) small parts of code e.g. for
394// debugging and other types of instrumentation. When using the code patcher
395// the exact number of bytes specified must be emitted. It is not legal to emit
396// relocation information. If any of these constraints are violated it causes
397// an assertion to fail.
398class CodePatcher {
399 public:
400 CodePatcher(byte* address, int instructions);
401 virtual ~CodePatcher();
402
403 // Macro assembler to emit code.
404 MacroAssembler* masm() { return &masm_; }
405
406 // Emit an instruction directly.
407 void Emit(Instr x);
408
409 // Emit an address directly.
410 void Emit(Address addr);
411
412 private:
413 byte* address_; // The address of the code being patched.
414 int instructions_; // Number of instructions of the expected patch size.
415 int size_; // Number of bytes of the expected patch size.
416 MacroAssembler masm_; // Macro assembler used to generate the code.
417};
418#endif // ENABLE_DEBUGGER_SUPPORT
419
420
421// -----------------------------------------------------------------------------
422// Static helper functions.
423
424// Generate a MemOperand for loading a field from an object.
425static inline MemOperand FieldMemOperand(Register object, int offset) {
426 return MemOperand(object, offset - kHeapObjectTag);
427}
428
429
430#ifdef GENERATED_CODE_COVERAGE
431#define CODE_COVERAGE_STRINGIFY(x) #x
432#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
433#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
434#define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
435#else
436#define ACCESS_MASM(masm) masm->
437#endif
438
439
440} } // namespace v8::internal
441
442#endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_