blob: 340055ad86055e25045532a4320b7f69cb89d36b [file] [log] [blame]
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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
ager@chromium.org5ec48922009-05-05 07:25:34 +000028#ifndef V8_IA32_MACRO_ASSEMBLER_IA32_H_
29#define V8_IA32_MACRO_ASSEMBLER_IA32_H_
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000030
31#include "assembler.h"
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000032#include "frames.h"
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +000033#include "v8globals.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000034
kasperl@chromium.org71affb52009-05-26 05:44:31 +000035namespace v8 {
36namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037
fschneider@chromium.org0c20e672010-01-14 15:28:53 +000038// Convenience for platform-independent signatures. We do not normally
39// distinguish memory operands from other operands on ia32.
40typedef Operand MemOperand;
41
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000042enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
43enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
44
45
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +000046enum RegisterValueType {
47 REGISTER_VALUE_IS_SMI,
48 REGISTER_VALUE_IS_INT32
49};
50
51
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000052bool AreAliased(Register r1, Register r2, Register r3, Register r4);
53
54
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000055// MacroAssembler implements a collection of frequently used macros.
56class MacroAssembler: public Assembler {
57 public:
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000058 // The isolate parameter can be NULL if the macro assembler should
59 // not use isolate-dependent functionality. In this case, it's the
60 // responsibility of the caller to never invoke such function on the
61 // macro assembler.
62 MacroAssembler(Isolate* isolate, void* buffer, int size);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000063
64 // ---------------------------------------------------------------------------
65 // GC Support
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000066 enum RememberedSetFinalAction {
67 kReturnAtEnd,
68 kFallThroughAtEnd
69 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000070
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000071 // Record in the remembered set the fact that we have a pointer to new space
72 // at the address pointed to by the addr register. Only works if addr is not
73 // in new space.
74 void RememberedSetHelper(Register object, // Used for debug code.
75 Register addr,
76 Register scratch,
77 SaveFPRegsMode save_fp,
78 RememberedSetFinalAction and_then);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000079
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000080 void CheckPageFlag(Register object,
81 Register scratch,
82 int mask,
83 Condition cc,
84 Label* condition_met,
85 Label::Distance condition_met_distance = Label::kFar);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +000086
mmassi@chromium.org7028c052012-06-13 11:51:58 +000087 void CheckPageFlagForMap(
88 Handle<Map> map,
89 int mask,
90 Condition cc,
91 Label* condition_met,
92 Label::Distance condition_met_distance = Label::kFar);
93
danno@chromium.orgf005df62013-04-30 16:36:45 +000094 void CheckMapDeprecated(Handle<Map> map,
95 Register scratch,
96 Label* if_deprecated);
97
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000098 // Check if object is in new space. Jumps if the object is not in new space.
99 // The register scratch can be object itself, but scratch will be clobbered.
100 void JumpIfNotInNewSpace(Register object,
101 Register scratch,
102 Label* branch,
103 Label::Distance distance = Label::kFar) {
104 InNewSpace(object, scratch, zero, branch, distance);
105 }
106
107 // Check if object is in new space. Jumps if the object is in new space.
108 // The register scratch can be object itself, but it will be clobbered.
109 void JumpIfInNewSpace(Register object,
110 Register scratch,
111 Label* branch,
112 Label::Distance distance = Label::kFar) {
113 InNewSpace(object, scratch, not_zero, branch, distance);
114 }
115
116 // Check if an object has a given incremental marking color. Also uses ecx!
117 void HasColor(Register object,
118 Register scratch0,
119 Register scratch1,
120 Label* has_color,
121 Label::Distance has_color_distance,
122 int first_bit,
123 int second_bit);
124
125 void JumpIfBlack(Register object,
126 Register scratch0,
127 Register scratch1,
128 Label* on_black,
129 Label::Distance on_black_distance = Label::kFar);
130
131 // Checks the color of an object. If the object is already grey or black
132 // then we just fall through, since it is already live. If it is white and
133 // we can determine that it doesn't need to be scanned, then we just mark it
134 // black and fall through. For the rest we jump to the label so the
135 // incremental marker can fix its assumptions.
136 void EnsureNotWhite(Register object,
137 Register scratch1,
138 Register scratch2,
139 Label* object_is_white_and_not_data,
140 Label::Distance distance);
141
142 // Notify the garbage collector that we wrote a pointer into an object.
143 // |object| is the object being stored into, |value| is the object being
144 // stored. value and scratch registers are clobbered by the operation.
145 // The offset is the offset from the start of the object, not the offset from
146 // the tagged HeapObject pointer. For use with FieldOperand(reg, off).
147 void RecordWriteField(
148 Register object,
149 int offset,
150 Register value,
151 Register scratch,
152 SaveFPRegsMode save_fp,
153 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
154 SmiCheck smi_check = INLINE_SMI_CHECK);
155
156 // As above, but the offset has the tag presubtracted. For use with
157 // Operand(reg, off).
158 void RecordWriteContextSlot(
159 Register context,
160 int offset,
161 Register value,
162 Register scratch,
163 SaveFPRegsMode save_fp,
164 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
165 SmiCheck smi_check = INLINE_SMI_CHECK) {
166 RecordWriteField(context,
167 offset + kHeapObjectTag,
168 value,
169 scratch,
170 save_fp,
171 remembered_set_action,
172 smi_check);
173 }
174
175 // Notify the garbage collector that we wrote a pointer into a fixed array.
176 // |array| is the array being stored into, |value| is the
177 // object being stored. |index| is the array index represented as a
178 // Smi. All registers are clobbered by the operation RecordWriteArray
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000179 // filters out smis so it does not update the write barrier if the
180 // value is a smi.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000181 void RecordWriteArray(
182 Register array,
183 Register value,
184 Register index,
185 SaveFPRegsMode save_fp,
186 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
187 SmiCheck smi_check = INLINE_SMI_CHECK);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000189 // For page containing |object| mark region covering |address|
190 // dirty. |object| is the object being stored into, |value| is the
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000191 // object being stored. The address and value registers are clobbered by the
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000192 // operation. RecordWrite filters out smis so it does not update the
193 // write barrier if the value is a smi.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000194 void RecordWrite(
195 Register object,
196 Register address,
197 Register value,
198 SaveFPRegsMode save_fp,
199 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
200 SmiCheck smi_check = INLINE_SMI_CHECK);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000201
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000202 // For page containing |object| mark the region covering the object's map
203 // dirty. |object| is the object being stored into, |map| is the Map object
204 // that was stored.
205 void RecordWriteForMap(
206 Register object,
207 Handle<Map> map,
208 Register scratch1,
209 Register scratch2,
210 SaveFPRegsMode save_fp);
211
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000212#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000213 // ---------------------------------------------------------------------------
214 // Debugger Support
215
ager@chromium.org5c838252010-02-19 08:53:10 +0000216 void DebugBreak();
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000217#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000218
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000219 // Enter specific kind of exit frame. Expects the number of
220 // arguments in register eax and sets up the number of arguments in
221 // register edi and the pointer to the first argument in register
222 // esi.
223 void EnterExitFrame(bool save_doubles);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000224
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000225 void EnterApiExitFrame(int argc);
ager@chromium.org236ad962008-09-25 09:45:57 +0000226
227 // Leave the current exit frame. Expects the return value in
228 // register eax:edx (untouched) and the pointer to the first
229 // argument in register esi.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000230 void LeaveExitFrame(bool save_doubles);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000231
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000232 // Leave the current exit frame. Expects the return value in
233 // register eax (untouched).
234 void LeaveApiExitFrame();
235
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000236 // Find the function context up the context chain.
237 void LoadContext(Register dst, int context_chain_length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000238
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +0000239 // Conditionally load the cached Array transitioned map of type
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000240 // transitioned_kind from the native context if the map in register
241 // map_in_out is the cached Array map in the native context of
jkummerow@chromium.org1145ef82012-02-02 16:21:15 +0000242 // expected_kind.
243 void LoadTransitionedArrayMapConditional(
244 ElementsKind expected_kind,
245 ElementsKind transitioned_kind,
246 Register map_in_out,
247 Register scratch,
248 Label* no_map_match);
249
250 // Load the initial map for new Arrays from a JSFunction.
251 void LoadInitialArrayMap(Register function_in,
252 Register scratch,
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000253 Register map_out,
254 bool can_have_holes);
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000255
yangguo@chromium.org4a9f6552013-03-04 14:46:33 +0000256 void LoadGlobalContext(Register global_context);
257
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000258 // Load the global function with the given index.
259 void LoadGlobalFunction(int index, Register function);
260
261 // Load the initial map from the global function. The registers
262 // function and map can be the same.
263 void LoadGlobalFunctionInitialMap(Register function, Register map);
264
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000265 // Push and pop the registers that can hold pointers.
266 void PushSafepointRegisters() { pushad(); }
267 void PopSafepointRegisters() { popad(); }
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000268 // Store the value in register/immediate src in the safepoint
269 // register stack slot for register dst.
270 void StoreToSafepointRegisterSlot(Register dst, Register src);
271 void StoreToSafepointRegisterSlot(Register dst, Immediate src);
272 void LoadFromSafepointRegisterSlot(Register dst, Register src);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000273
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000274 void LoadHeapObject(Register result, Handle<HeapObject> object);
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000275 void CmpHeapObject(Register reg, Handle<HeapObject> object);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000276 void PushHeapObject(Handle<HeapObject> object);
277
danno@chromium.orgbf0c8202011-12-27 10:09:42 +0000278 void LoadObject(Register result, Handle<Object> object) {
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000279 ALLOW_HANDLE_DEREF(isolate(), "heap object check");
danno@chromium.orgbf0c8202011-12-27 10:09:42 +0000280 if (object->IsHeapObject()) {
281 LoadHeapObject(result, Handle<HeapObject>::cast(object));
282 } else {
283 Set(result, Immediate(object));
284 }
285 }
286
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000287 void CmpObject(Register reg, Handle<Object> object) {
288 ALLOW_HANDLE_DEREF(isolate(), "heap object check");
289 if (object->IsHeapObject()) {
290 CmpHeapObject(reg, Handle<HeapObject>::cast(object));
291 } else {
292 cmp(reg, Immediate(object));
293 }
294 }
295
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000296 // ---------------------------------------------------------------------------
297 // JavaScript invokes
298
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000299 // Set up call kind marking in ecx. The method takes ecx as an
danno@chromium.org40cb8782011-05-25 07:58:50 +0000300 // explicit first parameter to make the code more readable at the
301 // call sites.
302 void SetCallKind(Register dst, CallKind kind);
303
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000304 // Invoke the JavaScript function code by either calling or jumping.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000305 void InvokeCode(Register code,
306 const ParameterCount& expected,
307 const ParameterCount& actual,
308 InvokeFlag flag,
309 const CallWrapper& call_wrapper,
310 CallKind call_kind) {
311 InvokeCode(Operand(code), expected, actual, flag, call_wrapper, call_kind);
312 }
313
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000314 void InvokeCode(const Operand& code,
315 const ParameterCount& expected,
316 const ParameterCount& actual,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000317 InvokeFlag flag,
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000318 const CallWrapper& call_wrapper,
319 CallKind call_kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000320
321 void InvokeCode(Handle<Code> code,
322 const ParameterCount& expected,
323 const ParameterCount& actual,
ager@chromium.org236ad962008-09-25 09:45:57 +0000324 RelocInfo::Mode rmode,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000325 InvokeFlag flag,
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000326 const CallWrapper& call_wrapper,
327 CallKind call_kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000328
329 // Invoke the JavaScript function in the given register. Changes the
330 // current context to the context in the function before invoking.
331 void InvokeFunction(Register function,
332 const ParameterCount& actual,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000333 InvokeFlag flag,
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000334 const CallWrapper& call_wrapper,
335 CallKind call_kind);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000336
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000337 void InvokeFunction(Handle<JSFunction> function,
ulan@chromium.org32d7dba2013-04-24 10:59:06 +0000338 const ParameterCount& expected,
ager@chromium.org5c838252010-02-19 08:53:10 +0000339 const ParameterCount& actual,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000340 InvokeFlag flag,
ricow@chromium.orgd2be9012011-06-01 06:00:58 +0000341 const CallWrapper& call_wrapper,
342 CallKind call_kind);
ager@chromium.org5c838252010-02-19 08:53:10 +0000343
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000344 // Invoke specified builtin JavaScript function. Adds an entry to
345 // the unresolved list if the name does not resolve.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000346 void InvokeBuiltin(Builtins::JavaScript id,
347 InvokeFlag flag,
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +0000348 const CallWrapper& call_wrapper = NullCallWrapper());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000349
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000350 // Store the function for the given builtin in the target register.
351 void GetBuiltinFunction(Register target, Builtins::JavaScript id);
352
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000353 // Store the code object for the given builtin in the target register.
354 void GetBuiltinEntry(Register target, Builtins::JavaScript id);
355
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000356 // Expression support
357 void Set(Register dst, const Immediate& x);
358 void Set(const Operand& dst, const Immediate& x);
359
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000360 // Support for constant splitting.
361 bool IsUnsafeImmediate(const Immediate& x);
362 void SafeSet(Register dst, const Immediate& x);
363 void SafePush(const Immediate& x);
364
ricow@chromium.org7ad65222011-12-19 12:13:11 +0000365 // Compare against a known root, e.g. undefined, null, true, ...
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000366 void CompareRoot(Register with, Heap::RootListIndex index);
ricow@chromium.org7ad65222011-12-19 12:13:11 +0000367 void CompareRoot(const Operand& with, Heap::RootListIndex index);
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000368
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000369 // Compare object type for heap object.
370 // Incoming register is heap_object and outgoing register is map.
371 void CmpObjectType(Register heap_object, InstanceType type, Register map);
372
373 // Compare instance type for map.
374 void CmpInstanceType(Register map, InstanceType type);
375
erik.corry@gmail.comd6076d92011-06-06 09:39:18 +0000376 // Check if a map for a JSObject indicates that the object has fast elements.
377 // Jump to the specified label if it does not.
378 void CheckFastElements(Register map,
379 Label* fail,
380 Label::Distance distance = Label::kFar);
381
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000382 // Check if a map for a JSObject indicates that the object can have both smi
383 // and HeapObject elements. Jump to the specified label if it does not.
384 void CheckFastObjectElements(Register map,
385 Label* fail,
386 Label::Distance distance = Label::kFar);
387
388 // Check if a map for a JSObject indicates that the object has fast smi only
389 // elements. Jump to the specified label if it does not.
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000390 void CheckFastSmiElements(Register map,
391 Label* fail,
392 Label::Distance distance = Label::kFar);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000393
394 // Check to see if maybe_number can be stored as a double in
395 // FastDoubleElements. If it can, store it at the index specified by key in
396 // the FastDoubleElements array elements, otherwise jump to fail.
397 void StoreNumberToDoubleElements(Register maybe_number,
398 Register elements,
399 Register key,
400 Register scratch1,
401 XMMRegister scratch2,
402 Label* fail,
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000403 bool specialize_for_processor,
404 int offset = 0);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000405
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000406 // Compare an object's map with the specified map and its transitioned
407 // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. FLAGS are set with
408 // result of map compare. If multiple map compares are required, the compare
409 // sequences branches to early_success.
410 void CompareMap(Register obj,
411 Handle<Map> map,
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000412 Label* early_success);
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000413
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000414 // Check if the map of an object is equal to a specified map and branch to
415 // label if not. Skip the smi check if not required (object is known to be a
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000416 // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000417 // against maps that are ElementsKind transition maps of the specified map.
ager@chromium.org5c838252010-02-19 08:53:10 +0000418 void CheckMap(Register obj,
419 Handle<Map> map,
420 Label* fail,
svenpanne@chromium.orga53e8e02013-05-24 12:35:50 +0000421 SmiCheckType smi_check_type);
ager@chromium.org5c838252010-02-19 08:53:10 +0000422
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000423 // Check if the map of an object is equal to a specified map and branch to a
424 // specified target if equal. Skip the smi check if not required (object is
425 // known to be a heap object)
426 void DispatchMap(Register obj,
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000427 Register unused,
ager@chromium.orgea91cc52011-05-23 06:06:11 +0000428 Handle<Map> map,
429 Handle<Code> success,
430 SmiCheckType smi_check_type);
431
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000432 // Check if the object in register heap_object is a string. Afterwards the
433 // register map contains the object map and the register instance_type
434 // contains the instance_type. The registers map and instance_type can be the
435 // same in which case it contains the instance type afterwards. Either of the
436 // registers map and instance_type can be the same as heap_object.
437 Condition IsObjectStringType(Register heap_object,
438 Register map,
439 Register instance_type);
440
ulan@chromium.org750145a2013-03-07 15:14:13 +0000441 // Check if the object in register heap_object is a name. Afterwards the
442 // register map contains the object map and the register instance_type
443 // contains the instance_type. The registers map and instance_type can be the
444 // same in which case it contains the instance type afterwards. Either of the
445 // registers map and instance_type can be the same as heap_object.
446 Condition IsObjectNameType(Register heap_object,
447 Register map,
448 Register instance_type);
449
lrn@chromium.org1af7e1b2010-06-07 11:12:01 +0000450 // Check if a heap object's type is in the JSObject range, not including
451 // JSFunction. The object's map will be loaded in the map register.
452 // Any or all of the three registers may be the same.
453 // The contents of the scratch register will always be overwritten.
454 void IsObjectJSObjectType(Register heap_object,
455 Register map,
456 Register scratch,
457 Label* fail);
458
459 // The contents of the scratch register will be overwritten.
460 void IsInstanceJSObjectType(Register map, Register scratch, Label* fail);
461
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000462 // FCmp is similar to integer cmp, but requires unsigned
463 // jcc instructions (je, ja, jae, jb, jbe, je, and jz).
464 void FCmp();
465
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000466 void ClampUint8(Register reg);
467
468 void ClampDoubleToUint8(XMMRegister input_reg,
469 XMMRegister scratch_reg,
470 Register result_reg);
471
472
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000473 // Smi tagging support.
474 void SmiTag(Register reg) {
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +0000475 STATIC_ASSERT(kSmiTag == 0);
476 STATIC_ASSERT(kSmiTagSize == 1);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000477 add(reg, reg);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000478 }
479 void SmiUntag(Register reg) {
480 sar(reg, kSmiTagSize);
481 }
482
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000483 // Modifies the register even if it does not contain a Smi!
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000484 void SmiUntag(Register reg, Label* is_smi) {
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +0000485 STATIC_ASSERT(kSmiTagSize == 1);
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000486 sar(reg, kSmiTagSize);
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +0000487 STATIC_ASSERT(kSmiTag == 0);
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000488 j(not_carry, is_smi);
489 }
490
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000491 void LoadUint32(XMMRegister dst, Register src, XMMRegister scratch);
492
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000493 // Jump the register contains a smi.
whesse@chromium.org7b260152011-06-20 15:33:18 +0000494 inline void JumpIfSmi(Register value,
495 Label* smi_label,
496 Label::Distance distance = Label::kFar) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000497 test(value, Immediate(kSmiTagMask));
whesse@chromium.org7b260152011-06-20 15:33:18 +0000498 j(zero, smi_label, distance);
499 }
500 // Jump if the operand is a smi.
501 inline void JumpIfSmi(Operand value,
502 Label* smi_label,
503 Label::Distance distance = Label::kFar) {
504 test(value, Immediate(kSmiTagMask));
505 j(zero, smi_label, distance);
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000506 }
507 // Jump if register contain a non-smi.
whesse@chromium.org7b260152011-06-20 15:33:18 +0000508 inline void JumpIfNotSmi(Register value,
509 Label* not_smi_label,
510 Label::Distance distance = Label::kFar) {
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000511 test(value, Immediate(kSmiTagMask));
whesse@chromium.org7b260152011-06-20 15:33:18 +0000512 j(not_zero, not_smi_label, distance);
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000513 }
514
danno@chromium.org40cb8782011-05-25 07:58:50 +0000515 void LoadInstanceDescriptors(Register map, Register descriptors);
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000516 void EnumLength(Register dst, Register map);
verwaest@chromium.org06ab2ec2012-10-09 17:00:13 +0000517 void NumberOfOwnDescriptors(Register dst, Register map);
danno@chromium.org40cb8782011-05-25 07:58:50 +0000518
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000519 template<typename Field>
520 void DecodeField(Register reg) {
verwaest@chromium.org06ab2ec2012-10-09 17:00:13 +0000521 static const int shift = Field::kShift;
522 static const int mask = (Field::kMask >> Field::kShift) << kSmiTagSize;
523 sar(reg, shift);
524 and_(reg, Immediate(mask));
yangguo@chromium.org355cfd12012-08-29 15:32:24 +0000525 }
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000526 void LoadPowerOf2(XMMRegister dst, Register scratch, int power);
527
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +0000528 // Abort execution if argument is not a number, enabled via --debug-code.
529 void AssertNumber(Register object);
ager@chromium.org5c838252010-02-19 08:53:10 +0000530
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +0000531 // Abort execution if argument is not a smi, enabled via --debug-code.
532 void AssertSmi(Register object);
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000533
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +0000534 // Abort execution if argument is a smi, enabled via --debug-code.
535 void AssertNotSmi(Register object);
vegorov@chromium.org26c16f82010-08-11 13:41:03 +0000536
svenpanne@chromium.orgc859c4f2012-10-15 11:51:39 +0000537 // Abort execution if argument is not a string, enabled via --debug-code.
538 void AssertString(Register object);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000539
ulan@chromium.org750145a2013-03-07 15:14:13 +0000540 // Abort execution if argument is not a name, enabled via --debug-code.
541 void AssertName(Register object);
542
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000543 // ---------------------------------------------------------------------------
544 // Exception handling
545
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000546 // Push a new try handler and link it into try handler chain.
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000547 void PushTryHandler(StackHandler::Kind kind, int handler_index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000548
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000549 // Unlink the stack handler on top of the stack from the try handler chain.
550 void PopTryHandler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000551
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000552 // Throw to the top handler in the try hander chain.
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000553 void Throw(Register value);
554
ulan@chromium.org65a89c22012-02-14 11:46:07 +0000555 // Throw past all JS frames to the top JS entry frame.
556 void ThrowUncatchable(Register value);
kmillikin@chromium.org49edbdf2011-02-16 12:32:18 +0000557
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000558 // ---------------------------------------------------------------------------
559 // Inline caching support
560
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000561 // Generate code for checking access rights - used for security checks
562 // on access to global objects across environments. The holder register
563 // is left untouched, but the scratch register is clobbered.
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000564 void CheckAccessGlobalProxy(Register holder_reg,
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000565 Register scratch1,
566 Register scratch2,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000567 Label* miss);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000568
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000569 void GetNumberHash(Register r0, Register scratch);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000570
sgjesse@chromium.org6db88712011-07-11 11:41:22 +0000571 void LoadFromNumberDictionary(Label* miss,
572 Register elements,
573 Register key,
574 Register r0,
575 Register r1,
576 Register r2,
577 Register result);
578
579
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580 // ---------------------------------------------------------------------------
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000581 // Allocation support
582
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000583 // Allocate an object in new space or old pointer space. If the given space
584 // is exhausted control continues at the gc_required label. The allocated
585 // object is returned in result and end of the new object is returned in
586 // result_end. The register scratch can be passed as no_reg in which case
587 // an additional object reference will be added to the reloc info. The
588 // returned pointers in result and result_end have not yet been tagged as
589 // heap objects. If result_contains_top_on_entry is true the content of
590 // result is known to be the allocation top on entry (could be result_end
591 // from a previous call). If result_contains_top_on_entry is true scratch
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000592 // should be no_reg as it is never used.
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000593 void Allocate(int object_size,
594 Register result,
595 Register result_end,
596 Register scratch,
597 Label* gc_required,
598 AllocationFlags flags);
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000599
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000600 void Allocate(int header_size,
601 ScaleFactor element_size,
602 Register element_count,
603 RegisterValueType element_count_type,
604 Register result,
605 Register result_end,
606 Register scratch,
607 Label* gc_required,
608 AllocationFlags flags);
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000609
mstarzinger@chromium.orgf705b502013-04-04 11:38:09 +0000610 void Allocate(Register object_size,
611 Register result,
612 Register result_end,
613 Register scratch,
614 Label* gc_required,
615 AllocationFlags flags);
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000616
617 // Undo allocation in new space. The object passed and objects allocated after
618 // it will no longer be allocated. Make sure that no pointers are left to the
619 // object(s) no longer allocated as they would be invalid when allocation is
620 // un-done.
621 void UndoAllocationInNewSpace(Register object);
622
ager@chromium.org3811b432009-10-28 14:53:37 +0000623 // Allocate a heap number in new space with undefined value. The
624 // register scratch2 can be passed as no_reg; the others must be
625 // valid registers. Returns tagged pointer in result register, or
626 // jumps to gc_required if new space is full.
627 void AllocateHeapNumber(Register result,
628 Register scratch1,
629 Register scratch2,
630 Label* gc_required);
631
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000632 // Allocate a sequential string. All the header fields of the string object
633 // are initialized.
634 void AllocateTwoByteString(Register result,
635 Register length,
636 Register scratch1,
637 Register scratch2,
638 Register scratch3,
639 Label* gc_required);
640 void AllocateAsciiString(Register result,
641 Register length,
642 Register scratch1,
643 Register scratch2,
644 Register scratch3,
645 Label* gc_required);
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000646 void AllocateAsciiString(Register result,
647 int length,
648 Register scratch1,
649 Register scratch2,
650 Label* gc_required);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000651
652 // Allocate a raw cons string object. Only the map field of the result is
653 // initialized.
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000654 void AllocateTwoByteConsString(Register result,
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000655 Register scratch1,
656 Register scratch2,
657 Label* gc_required);
658 void AllocateAsciiConsString(Register result,
659 Register scratch1,
660 Register scratch2,
661 Label* gc_required);
662
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +0000663 // Allocate a raw sliced string object. Only the map field of the result is
664 // initialized.
fschneider@chromium.org1805e212011-09-05 10:49:12 +0000665 void AllocateTwoByteSlicedString(Register result,
yangguo@chromium.org80c42ed2011-08-31 09:03:56 +0000666 Register scratch1,
667 Register scratch2,
668 Label* gc_required);
669 void AllocateAsciiSlicedString(Register result,
670 Register scratch1,
671 Register scratch2,
672 Label* gc_required);
673
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000674 // Copy memory, byte-by-byte, from source to destination. Not optimized for
675 // long or aligned copies.
676 // The contents of index and scratch are destroyed.
677 void CopyBytes(Register source,
678 Register destination,
679 Register length,
680 Register scratch);
vegorov@chromium.org21b5e952010-11-23 10:24:40 +0000681
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000682 // Initialize fields with filler values. Fields starting at |start_offset|
683 // not including end_offset are overwritten with the value in |filler|. At
684 // the end the loop, |start_offset| takes the value of |end_offset|.
685 void InitializeFieldsWithFiller(Register start_offset,
686 Register end_offset,
687 Register filler);
688
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000689 // ---------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000690 // Support functions.
691
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000692 // Check a boolean-bit of a Smi field.
693 void BooleanBitTest(Register object, int field_offset, int bit_index);
694
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000695 // Check if result is zero and op is negative.
696 void NegativeZeroTest(Register result, Register op, Label* then_label);
697
698 // Check if result is zero and any of op1 and op2 are negative.
699 // Register scratch is destroyed, and it must be different from op2.
700 void NegativeZeroTest(Register result, Register op1, Register op2,
701 Register scratch, Label* then_label);
702
ager@chromium.org7c537e22008-10-16 08:43:32 +0000703 // Try to get function prototype of a function and puts the value in
704 // the result register. Checks that the function really is a
705 // function and jumps to the miss label if the fast checks fail. The
706 // function register will be untouched; the other registers may be
707 // clobbered.
708 void TryGetFunctionPrototype(Register function,
709 Register result,
710 Register scratch,
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000711 Label* miss,
712 bool miss_on_bound_function = false);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000713
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000714 // Generates code for reporting that an illegal operation has
kasperl@chromium.org41044eb2008-10-06 08:24:46 +0000715 // occurred.
716 void IllegalOperation(int num_arguments);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000717
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000718 // Picks out an array index from the hash field.
719 // Register use:
720 // hash - holds the index's hash. Clobbered.
721 // index - holds the overwritten index on exit.
722 void IndexFromHash(Register hash, Register index);
723
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000724 // ---------------------------------------------------------------------------
725 // Runtime calls
726
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000727 // Call a code stub. Generate the code if necessary.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000728 void CallStub(CodeStub* stub, TypeFeedbackId ast_id = TypeFeedbackId::None());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000729
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000730 // Tail call a code stub (jump). Generate the code if necessary.
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000731 void TailCallStub(CodeStub* stub);
732
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000733 // Return from a code stub after popping its arguments.
734 void StubReturn(int argc);
735
736 // Call a runtime routine.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000737 void CallRuntime(const Runtime::Function* f, int num_arguments);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000738 void CallRuntimeSaveDoubles(Runtime::FunctionId id);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000739
740 // Convenience function: Same as above, but takes the fid instead.
741 void CallRuntime(Runtime::FunctionId id, int num_arguments);
742
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000743 // Convenience function: call an external reference.
744 void CallExternalReference(ExternalReference ref, int num_arguments);
745
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000746 // Tail call of a runtime routine (jump).
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000747 // Like JumpToExternalReference, but also takes care of passing the number
748 // of parameters.
749 void TailCallExternalReference(const ExternalReference& ext,
750 int num_arguments,
751 int result_size);
752
753 // Convenience function: tail call a runtime routine (jump).
754 void TailCallRuntime(Runtime::FunctionId fid,
ager@chromium.orga1645e22009-09-09 19:27:10 +0000755 int num_arguments,
756 int result_size);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000757
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000758 // Before calling a C-function from generated code, align arguments on stack.
759 // After aligning the frame, arguments must be stored in esp[0], esp[4],
760 // etc., not pushed. The argument count assumes all arguments are word sized.
761 // Some compilers/platforms require the stack to be aligned when calling
762 // C++ code.
763 // Needs a scratch register to do some arithmetic. This register will be
764 // trashed.
765 void PrepareCallCFunction(int num_arguments, Register scratch);
766
767 // Calls a C function and cleans up the space for arguments allocated
768 // by PrepareCallCFunction. The called function is not allowed to trigger a
769 // garbage collection, since that might move the code and invalidate the
770 // return address (unless this is somehow accounted for by the called
771 // function).
772 void CallCFunction(ExternalReference function, int num_arguments);
773 void CallCFunction(Register function, int num_arguments);
774
lrn@chromium.org303ada72010-10-27 09:33:13 +0000775 // Prepares stack to put arguments (aligns and so on). Reserves
776 // space for return value if needed (assumes the return value is a handle).
jkummerow@chromium.orgddda9e82011-07-06 11:27:02 +0000777 // Arguments must be stored in ApiParameterOperand(0), ApiParameterOperand(1)
778 // etc. Saves context (esi). If space was reserved for return value then
779 // stores the pointer to the reserved slot into esi.
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000780 void PrepareCallApiFunction(int argc, bool returns_handle);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000781
jkummerow@chromium.orgc3b37122011-11-07 10:14:12 +0000782 // Calls an API function. Allocates HandleScope, extracts returned value
783 // from handle and propagates exceptions. Clobbers ebx, edi and
784 // caller-save registers. Restores context. On return removes
785 // stack_space * kPointerSize (GCed).
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000786 void CallApiFunctionAndReturn(Address function_address,
787 int stack_space,
788 bool returns_handle,
789 int return_value_offset_from_ebp);
kmillikin@chromium.org2d5475f2009-12-20 18:15:52 +0000790
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000791 // Jump to a runtime routine.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000792 void JumpToExternalReference(const ExternalReference& ext);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000793
ager@chromium.org236ad962008-09-25 09:45:57 +0000794 // ---------------------------------------------------------------------------
795 // Utilities
796
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000797 void Ret();
798
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000799 // Return and drop arguments from stack, where the number of arguments
800 // may be bigger than 2^16 - 1. Requires a scratch register.
801 void Ret(int bytes_dropped, Register scratch);
802
fschneider@chromium.org0c20e672010-01-14 15:28:53 +0000803 // Emit code to discard a non-negative number of pointer-sized elements
804 // from the stack, clobbering only the esp register.
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000805 void Drop(int element_count);
806
807 void Call(Label* target) { call(target); }
808
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000809 // Emit call to the code we are currently generating.
810 void CallSelf() {
811 Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
812 call(self, RelocInfo::CODE_TARGET);
813 }
814
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000815 // Move if the registers are not identical.
816 void Move(Register target, Register source);
817
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000818 // Push a handle value.
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000819 void Push(Handle<Object> handle) { push(Immediate(handle)); }
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000820 void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000821
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000822 Handle<Object> CodeObject() {
823 ASSERT(!code_object_.is_null());
824 return code_object_;
825 }
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000826
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000827 // Insert code to verify that the x87 stack has the specified depth (0-7)
828 void VerifyX87StackDepth(uint32_t depth);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000829
830 // ---------------------------------------------------------------------------
831 // StatsCounter support
832
833 void SetCounter(StatsCounter* counter, int value);
834 void IncrementCounter(StatsCounter* counter, int value);
835 void DecrementCounter(StatsCounter* counter, int value);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000836 void IncrementCounter(Condition cc, StatsCounter* counter, int value);
837 void DecrementCounter(Condition cc, StatsCounter* counter, int value);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000838
839
840 // ---------------------------------------------------------------------------
841 // Debugging
842
843 // Calls Abort(msg) if the condition cc is not satisfied.
844 // Use --debug_code to enable.
845 void Assert(Condition cc, const char* msg);
846
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000847 void AssertFastElements(Register elements);
848
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000849 // Like Assert(), but always enabled.
850 void Check(Condition cc, const char* msg);
851
852 // Print a message to stdout and abort execution.
853 void Abort(const char* msg);
854
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000855 // Check that the stack is aligned.
856 void CheckStackAlignment();
857
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000858 // Verify restrictions about code generated in stubs.
859 void set_generating_stub(bool value) { generating_stub_ = value; }
860 bool generating_stub() { return generating_stub_; }
kasper.lund7276f142008-07-30 08:49:36 +0000861 void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
862 bool allow_stub_calls() { return allow_stub_calls_; }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000863 void set_has_frame(bool value) { has_frame_ = value; }
864 bool has_frame() { return has_frame_; }
865 inline bool AllowThisStubCall(CodeStub* stub);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000866
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000867 // ---------------------------------------------------------------------------
868 // String utilities.
869
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000870 // Check whether the instance type represents a flat ASCII string. Jump to the
ager@chromium.org5c838252010-02-19 08:53:10 +0000871 // label if not. If the instance type can be scratched specify same register
872 // for both instance type and scratch.
873 void JumpIfInstanceTypeIsNotSequentialAscii(Register instance_type,
874 Register scratch,
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000875 Label* on_not_flat_ascii_string);
ager@chromium.org5c838252010-02-19 08:53:10 +0000876
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000877 // Checks if both objects are sequential ASCII strings, and jumps to label
878 // if either is not.
879 void JumpIfNotBothSequentialAsciiStrings(Register object1,
880 Register object2,
881 Register scratch1,
882 Register scratch2,
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000883 Label* on_not_flat_ascii_strings);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000884
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000885 static int SafepointRegisterStackIndex(Register reg) {
886 return SafepointRegisterStackIndex(reg.code());
887 }
888
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000889 // Activation support.
890 void EnterFrame(StackFrame::Type type);
891 void LeaveFrame(StackFrame::Type type);
892
kmillikin@chromium.orgbe6bd102012-02-23 08:45:21 +0000893 // Expects object in eax and returns map with validated enum cache
894 // in eax. Assumes that any other register can be used as a scratch.
895 void CheckEnumCache(Label* call_runtime);
896
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000897 // AllocationSiteInfo support. Arrays may have an associated
898 // AllocationSiteInfo object that can be checked for in order to pretransition
899 // to another type.
900 // On entry, receiver_reg should point to the array object.
901 // scratch_reg gets clobbered.
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000902 // If allocation info is present, conditional code is set to equal
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000903 void TestJSArrayForAllocationSiteInfo(Register receiver_reg,
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000904 Register scratch_reg);
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000905
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000906 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000907 bool generating_stub_;
kasper.lund7276f142008-07-30 08:49:36 +0000908 bool allow_stub_calls_;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000909 bool has_frame_;
ager@chromium.org5c838252010-02-19 08:53:10 +0000910 // This handle will be patched with the code object on installation.
911 Handle<Object> code_object_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000912
913 // Helper functions for generating invokes.
914 void InvokePrologue(const ParameterCount& expected,
915 const ParameterCount& actual,
916 Handle<Code> code_constant,
917 const Operand& code_operand,
karlklose@chromium.org83a47282011-05-11 11:54:09 +0000918 Label* done,
ulan@chromium.org2efb9002012-01-19 15:36:35 +0000919 bool* definitely_mismatches,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000920 InvokeFlag flag,
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000921 Label::Distance done_distance,
danno@chromium.org40cb8782011-05-25 07:58:50 +0000922 const CallWrapper& call_wrapper = NullCallWrapper(),
923 CallKind call_kind = CALL_AS_METHOD);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000924
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000925 void EnterExitFramePrologue();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000926 void EnterExitFrameEpilogue(int argc, bool save_doubles);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000927
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +0000928 void LeaveExitFrameEpilogue();
929
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000930 // Allocation support helpers.
931 void LoadAllocationTopHelper(Register result,
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000932 Register scratch,
ager@chromium.orga1645e22009-09-09 19:27:10 +0000933 AllocationFlags flags);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000934
935 void UpdateAllocationTopHelper(Register result_end,
936 Register scratch,
937 AllocationFlags flags);
kmillikin@chromium.org2d5475f2009-12-20 18:15:52 +0000938
939 // Helper for PopHandleScope. Allowed to perform a GC and returns
940 // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and
941 // possibly returns a failure object indicating an allocation failure.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000942 MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved,
943 Register scratch,
944 bool gc_allowed);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000945
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000946 // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
947 void InNewSpace(Register object,
948 Register scratch,
949 Condition cc,
950 Label* condition_met,
951 Label::Distance condition_met_distance = Label::kFar);
952
953 // Helper for finding the mark bits for an address. Afterwards, the
954 // bitmap register points at the word with the mark bits and the mask
955 // the position of the first bit. Uses ecx as scratch and leaves addr_reg
956 // unchanged.
957 inline void GetMarkBits(Register addr_reg,
958 Register bitmap_reg,
959 Register mask_reg);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000960
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000961 // Helper for throwing exceptions. Compute a handler address and jump to
962 // it. See the implementation for register usage.
963 void JumpToHandlerEntry();
964
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000965 // Compute memory operands for safepoint stack slots.
966 Operand SafepointRegisterSlot(Register reg);
967 static int SafepointRegisterStackIndex(int reg_code);
968
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000969 // Needs access to SafepointRegisterStackIndex for compiled frame
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000970 // traversal.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000971 friend class StandardFrame;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000972};
973
974
975// The code patcher is used to patch (typically) small parts of code e.g. for
976// debugging and other types of instrumentation. When using the code patcher
977// the exact number of bytes specified must be emitted. Is not legal to emit
978// relocation information. If any of these constraints are violated it causes
979// an assertion.
980class CodePatcher {
981 public:
982 CodePatcher(byte* address, int size);
983 virtual ~CodePatcher();
984
985 // Macro assembler to emit code.
986 MacroAssembler* masm() { return &masm_; }
987
988 private:
989 byte* address_; // The address of the code being patched.
990 int size_; // Number of bytes of the expected patch size.
991 MacroAssembler masm_; // Macro assembler used to generate the code.
992};
993
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000994
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000995// -----------------------------------------------------------------------------
996// Static helper functions.
997
998// Generate an Operand for loading a field from an object.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +0000999inline Operand FieldOperand(Register object, int offset) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001000 return Operand(object, offset - kHeapObjectTag);
1001}
1002
1003
kasper.lund7276f142008-07-30 08:49:36 +00001004// Generate an Operand for loading an indexed field from an object.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001005inline Operand FieldOperand(Register object,
1006 Register index,
1007 ScaleFactor scale,
1008 int offset) {
kasper.lund7276f142008-07-30 08:49:36 +00001009 return Operand(object, index, scale, offset - kHeapObjectTag);
1010}
1011
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001012
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001013inline Operand ContextOperand(Register context, int index) {
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001014 return Operand(context, Context::SlotOffset(index));
1015}
1016
1017
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001018inline Operand GlobalObjectOperand() {
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001019 return ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX);
erik.corry@gmail.com4a6c3272010-11-18 12:04:40 +00001020}
1021
1022
lrn@chromium.org303ada72010-10-27 09:33:13 +00001023// Generates an Operand for saving parameters after PrepareCallApiFunction.
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001024Operand ApiParameterOperand(int index, bool returns_handle);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001025
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001026
1027#ifdef GENERATED_CODE_COVERAGE
1028extern void LogGeneratedCodeCoverage(const char* file_line);
1029#define CODE_COVERAGE_STRINGIFY(x) #x
1030#define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
1031#define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
1032#define ACCESS_MASM(masm) { \
1033 byte* ia32_coverage_function = \
1034 reinterpret_cast<byte*>(FUNCTION_ADDR(LogGeneratedCodeCoverage)); \
1035 masm->pushfd(); \
1036 masm->pushad(); \
1037 masm->push(Immediate(reinterpret_cast<int>(&__FILE_LINE__))); \
1038 masm->call(ia32_coverage_function, RelocInfo::RUNTIME_ENTRY); \
1039 masm->pop(eax); \
1040 masm->popad(); \
1041 masm->popfd(); \
1042 } \
1043 masm->
1044#else
1045#define ACCESS_MASM(masm) masm->
1046#endif
1047
1048
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001049} } // namespace v8::internal
1050
ager@chromium.org5ec48922009-05-05 07:25:34 +00001051#endif // V8_IA32_MACRO_ASSEMBLER_IA32_H_