blob: d62bed4bdf44281362406c8251c875e99662279a [file] [log] [blame]
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001// Copyright 2010 the V8 project authors. All rights reserved.
ager@chromium.org5ec48922009-05-05 07:25:34 +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
kasperl@chromium.org71affb52009-05-26 05:44:31 +000028#include "v8.h"
29
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +000030#if defined(V8_TARGET_ARCH_X64)
31
kasperl@chromium.org71affb52009-05-26 05:44:31 +000032#include "bootstrapper.h"
33#include "codegen-inl.h"
ager@chromium.orgeadaf222009-06-16 09:43:10 +000034#include "assembler-x64.h"
ager@chromium.orge2902be2009-06-08 12:21:35 +000035#include "macro-assembler-x64.h"
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +000036#include "serialize.h"
ager@chromium.orgeadaf222009-06-16 09:43:10 +000037#include "debug.h"
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +000038#include "heap.h"
kasperl@chromium.org71affb52009-05-26 05:44:31 +000039
40namespace v8 {
41namespace internal {
42
43MacroAssembler::MacroAssembler(void* buffer, int size)
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000044 : Assembler(buffer, size),
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000045 generating_stub_(false),
46 allow_stub_calls_(true),
47 code_object_(Heap::undefined_value()) {
kasperl@chromium.org71affb52009-05-26 05:44:31 +000048}
49
ager@chromium.orge2902be2009-06-08 12:21:35 +000050
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000051void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +000052 movq(destination, Operand(kRootRegister, index << kPointerSizeLog2));
ager@chromium.org18ad94b2009-09-02 08:22:29 +000053}
54
55
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +000056void MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) {
57 movq(Operand(kRootRegister, index << kPointerSizeLog2), source);
58}
59
60
ager@chromium.org18ad94b2009-09-02 08:22:29 +000061void MacroAssembler::PushRoot(Heap::RootListIndex index) {
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +000062 push(Operand(kRootRegister, index << kPointerSizeLog2));
ager@chromium.org18ad94b2009-09-02 08:22:29 +000063}
64
65
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000066void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) {
whesse@chromium.orgb6e43bb2010-04-14 09:36:28 +000067 cmpq(with, Operand(kRootRegister, index << kPointerSizeLog2));
ager@chromium.org18ad94b2009-09-02 08:22:29 +000068}
69
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +000070
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000071void MacroAssembler::CompareRoot(Operand with, Heap::RootListIndex index) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +000072 LoadRoot(kScratchRegister, index);
73 cmpq(with, kScratchRegister);
74}
75
76
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000077void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) {
78 CompareRoot(rsp, Heap::kStackLimitRootIndex);
79 j(below, on_stack_overflow);
80}
81
82
ager@chromium.orgac091b72010-05-05 07:34:42 +000083void MacroAssembler::RecordWriteHelper(Register object,
84 Register addr,
85 Register scratch) {
86 if (FLAG_debug_code) {
87 // Check that the object is not in new space.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000088 NearLabel not_in_new_space;
ager@chromium.orgac091b72010-05-05 07:34:42 +000089 InNewSpace(object, scratch, not_equal, &not_in_new_space);
90 Abort("new-space object passed to RecordWriteHelper");
91 bind(&not_in_new_space);
92 }
93
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +000094 // Compute the page start address from the heap object pointer, and reuse
95 // the 'object' register for it.
ricow@chromium.org30ce4112010-05-31 10:38:25 +000096 and_(object, Immediate(~Page::kPageAlignmentMask));
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +000097
ricow@chromium.org30ce4112010-05-31 10:38:25 +000098 // Compute number of region covering addr. See Page::GetRegionNumberForAddress
99 // method for more details.
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000100 shrl(addr, Immediate(Page::kRegionSizeLog2));
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000101 andl(addr, Immediate(Page::kPageAlignmentMask >> Page::kRegionSizeLog2));
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000102
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000103 // Set dirty mark for region.
104 bts(Operand(object, Page::kDirtyFlagOffset), addr);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000105}
106
107
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000108void MacroAssembler::RecordWrite(Register object,
109 int offset,
110 Register value,
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000111 Register index) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000112 // The compiled code assumes that record write doesn't change the
113 // context register, so we check that none of the clobbered
114 // registers are rsi.
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000115 ASSERT(!object.is(rsi) && !value.is(rsi) && !index.is(rsi));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000116
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000117 // First, check if a write barrier is even needed. The tests below
118 // catch stores of Smis and stores into young gen.
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000119 Label done;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000120 JumpIfSmi(value, &done);
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000121
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000122 RecordWriteNonSmi(object, offset, value, index);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000123 bind(&done);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000124
125 // Clobber all input registers when running with the debug-code flag
126 // turned on to provoke errors. This clobbering repeats the
127 // clobbering done inside RecordWriteNonSmi but it's necessary to
128 // avoid having the fast case for smis leave the registers
129 // unchanged.
130 if (FLAG_debug_code) {
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000131 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
132 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000133 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000134 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000135}
136
137
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000138void MacroAssembler::RecordWrite(Register object,
139 Register address,
140 Register value) {
141 // The compiled code assumes that record write doesn't change the
142 // context register, so we check that none of the clobbered
143 // registers are esi.
144 ASSERT(!object.is(rsi) && !value.is(rsi) && !address.is(rsi));
145
146 // First, check if a write barrier is even needed. The tests below
147 // catch stores of Smis and stores into young gen.
148 Label done;
149 JumpIfSmi(value, &done);
150
151 InNewSpace(object, value, equal, &done);
152
153 RecordWriteHelper(object, address, value);
154
155 bind(&done);
156
157 // Clobber all input registers when running with the debug-code flag
158 // turned on to provoke errors.
159 if (FLAG_debug_code) {
160 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
161 movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
162 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
163 }
164}
165
166
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000167void MacroAssembler::RecordWriteNonSmi(Register object,
168 int offset,
169 Register scratch,
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000170 Register index) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000171 Label done;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000172
173 if (FLAG_debug_code) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000174 NearLabel okay;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000175 JumpIfNotSmi(object, &okay);
176 Abort("MacroAssembler::RecordWriteNonSmi cannot deal with smis");
177 bind(&okay);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000178
179 if (offset == 0) {
180 // index must be int32.
181 Register tmp = index.is(rax) ? rbx : rax;
182 push(tmp);
183 movl(tmp, index);
184 cmpq(tmp, index);
185 Check(equal, "Index register for RecordWrite must be untagged int32.");
186 pop(tmp);
187 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000188 }
189
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000190 // Test that the object address is not in the new space. We cannot
191 // update page dirty marks for new space pages.
kmillikin@chromium.org4111b802010-05-03 10:34:42 +0000192 InNewSpace(object, scratch, equal, &done);
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000193
whesse@chromium.orge88a9ed2010-04-15 15:07:46 +0000194 // The offset is relative to a tagged or untagged HeapObject pointer,
195 // so either offset or offset + kHeapObjectTag must be a
196 // multiple of kPointerSize.
197 ASSERT(IsAligned(offset, kPointerSize) ||
198 IsAligned(offset + kHeapObjectTag, kPointerSize));
199
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000200 Register dst = index;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000201 if (offset != 0) {
202 lea(dst, Operand(object, offset));
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000203 } else {
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000204 // array access: calculate the destination address in the same manner as
205 // KeyedStoreIC::GenerateGeneric.
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000206 lea(dst, FieldOperand(object,
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000207 index,
208 times_pointer_size,
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000209 FixedArray::kHeaderSize));
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000210 }
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000211 RecordWriteHelper(object, dst, scratch);
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000212
213 bind(&done);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000214
215 // Clobber all input registers when running with the debug-code flag
216 // turned on to provoke errors.
217 if (FLAG_debug_code) {
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000218 movq(object, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
219 movq(scratch, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000220 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000221 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000222}
223
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000224void MacroAssembler::Assert(Condition cc, const char* msg) {
225 if (FLAG_debug_code) Check(cc, msg);
226}
227
228
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000229void MacroAssembler::AssertFastElements(Register elements) {
230 if (FLAG_debug_code) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000231 NearLabel ok;
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000232 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
233 Heap::kFixedArrayMapRootIndex);
234 j(equal, &ok);
235 CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
236 Heap::kFixedCOWArrayMapRootIndex);
237 j(equal, &ok);
238 Abort("JSObject with fast elements map has slow elements");
239 bind(&ok);
240 }
241}
242
243
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000244void MacroAssembler::Check(Condition cc, const char* msg) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000245 NearLabel L;
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000246 j(cc, &L);
247 Abort(msg);
248 // will not return here
249 bind(&L);
250}
251
252
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000253void MacroAssembler::CheckStackAlignment() {
254 int frame_alignment = OS::ActivationFrameAlignment();
255 int frame_alignment_mask = frame_alignment - 1;
256 if (frame_alignment > kPointerSize) {
257 ASSERT(IsPowerOf2(frame_alignment));
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000258 NearLabel alignment_as_expected;
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000259 testq(rsp, Immediate(frame_alignment_mask));
260 j(zero, &alignment_as_expected);
261 // Abort if stack is not aligned.
262 int3();
263 bind(&alignment_as_expected);
264 }
265}
266
267
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000268void MacroAssembler::NegativeZeroTest(Register result,
269 Register op,
270 Label* then_label) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000271 NearLabel ok;
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000272 testl(result, result);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000273 j(not_zero, &ok);
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000274 testl(op, op);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000275 j(sign, then_label);
276 bind(&ok);
277}
278
279
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000280void MacroAssembler::Abort(const char* msg) {
281 // We want to pass the msg string like a smi to avoid GC
282 // problems, however msg is not guaranteed to be aligned
283 // properly. Instead, we pass an aligned pointer that is
284 // a proper v8 smi, but also pass the alignment difference
285 // from the real pointer as a smi.
286 intptr_t p1 = reinterpret_cast<intptr_t>(msg);
287 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
288 // Note: p0 might not be a valid Smi *value*, but it has a valid Smi tag.
289 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
290#ifdef DEBUG
291 if (msg != NULL) {
292 RecordComment("Abort message: ");
293 RecordComment(msg);
294 }
295#endif
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000296 // Disable stub call restrictions to always allow calls to abort.
297 set_allow_stub_calls(true);
298
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000299 push(rax);
300 movq(kScratchRegister, p0, RelocInfo::NONE);
301 push(kScratchRegister);
302 movq(kScratchRegister,
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000303 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(p1 - p0))),
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000304 RelocInfo::NONE);
305 push(kScratchRegister);
306 CallRuntime(Runtime::kAbort, 2);
307 // will not return here
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000308 int3();
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000309}
310
311
312void MacroAssembler::CallStub(CodeStub* stub) {
313 ASSERT(allow_stub_calls()); // calls are not allowed in some stubs
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000314 Call(stub->GetCode(), RelocInfo::CODE_TARGET);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000315}
316
317
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000318Object* MacroAssembler::TryCallStub(CodeStub* stub) {
319 ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
320 Object* result = stub->TryGetCode();
321 if (!result->IsFailure()) {
322 call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET);
323 }
324 return result;
325}
326
327
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000328void MacroAssembler::TailCallStub(CodeStub* stub) {
329 ASSERT(allow_stub_calls()); // calls are not allowed in some stubs
330 Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
331}
332
333
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000334Object* MacroAssembler::TryTailCallStub(CodeStub* stub) {
335 ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
336 Object* result = stub->TryGetCode();
337 if (!result->IsFailure()) {
338 jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET);
339 }
340 return result;
341}
342
343
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000344void MacroAssembler::StubReturn(int argc) {
345 ASSERT(argc >= 1 && generating_stub());
346 ret((argc - 1) * kPointerSize);
347}
348
349
350void MacroAssembler::IllegalOperation(int num_arguments) {
351 if (num_arguments > 0) {
352 addq(rsp, Immediate(num_arguments * kPointerSize));
353 }
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000354 LoadRoot(rax, Heap::kUndefinedValueRootIndex);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000355}
356
357
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000358void MacroAssembler::IndexFromHash(Register hash, Register index) {
359 // The assert checks that the constants for the maximum number of digits
360 // for an array index cached in the hash field and the number of bits
361 // reserved for it does not conflict.
362 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
363 (1 << String::kArrayIndexValueBits));
364 // We want the smi-tagged index in key. Even if we subsequently go to
365 // the slow case, converting the key to a smi is always valid.
366 // key: string key
367 // hash: key's hash field, including its array index value.
368 and_(hash, Immediate(String::kArrayIndexValueMask));
369 shr(hash, Immediate(String::kHashShift));
370 // Here we actually clobber the key which will be used if calling into
371 // runtime later. However as the new key is the numeric value of a string key
372 // there is no difference in using either key.
373 Integer32ToSmi(index, hash);
374}
375
376
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000377void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) {
378 CallRuntime(Runtime::FunctionForId(id), num_arguments);
379}
380
381
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000382Object* MacroAssembler::TryCallRuntime(Runtime::FunctionId id,
383 int num_arguments) {
384 return TryCallRuntime(Runtime::FunctionForId(id), num_arguments);
385}
386
387
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000388void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
389 // If the expected number of arguments of the runtime function is
390 // constant, we check that the actual number of arguments match the
391 // expectation.
392 if (f->nargs >= 0 && f->nargs != num_arguments) {
393 IllegalOperation(num_arguments);
394 return;
395 }
396
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000397 // TODO(1236192): Most runtime routines don't need the number of
398 // arguments passed in because it is constant. At some point we
399 // should remove this need and make the runtime routine entry code
400 // smarter.
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000401 Set(rax, num_arguments);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000402 movq(rbx, ExternalReference(f));
403 CEntryStub ces(f->result_size);
404 CallStub(&ces);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000405}
406
407
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000408Object* MacroAssembler::TryCallRuntime(Runtime::Function* f,
409 int num_arguments) {
410 if (f->nargs >= 0 && f->nargs != num_arguments) {
411 IllegalOperation(num_arguments);
412 // Since we did not call the stub, there was no allocation failure.
413 // Return some non-failure object.
414 return Heap::undefined_value();
415 }
416
417 // TODO(1236192): Most runtime routines don't need the number of
418 // arguments passed in because it is constant. At some point we
419 // should remove this need and make the runtime routine entry code
420 // smarter.
421 Set(rax, num_arguments);
422 movq(rbx, ExternalReference(f));
423 CEntryStub ces(f->result_size);
424 return TryCallStub(&ces);
425}
426
427
ager@chromium.org5c838252010-02-19 08:53:10 +0000428void MacroAssembler::CallExternalReference(const ExternalReference& ext,
429 int num_arguments) {
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000430 Set(rax, num_arguments);
ager@chromium.org5c838252010-02-19 08:53:10 +0000431 movq(rbx, ext);
432
433 CEntryStub stub(1);
434 CallStub(&stub);
435}
436
437
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000438void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
439 int num_arguments,
440 int result_size) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000441 // ----------- S t a t e -------------
442 // -- rsp[0] : return address
443 // -- rsp[8] : argument num_arguments - 1
444 // ...
445 // -- rsp[8 * num_arguments] : argument 0 (receiver)
446 // -----------------------------------
447
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000448 // TODO(1236192): Most runtime routines don't need the number of
449 // arguments passed in because it is constant. At some point we
450 // should remove this need and make the runtime routine entry code
451 // smarter.
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000452 Set(rax, num_arguments);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000453 JumpToExternalReference(ext, result_size);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000454}
455
456
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000457void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
458 int num_arguments,
459 int result_size) {
460 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
461}
462
463
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000464static int Offset(ExternalReference ref0, ExternalReference ref1) {
465 int64_t offset = (ref0.address() - ref1.address());
466 // Check that fits into int.
467 ASSERT(static_cast<int>(offset) == offset);
468 return static_cast<int>(offset);
469}
470
471
472void MacroAssembler::PushHandleScope(Register scratch) {
473 ExternalReference extensions_address =
474 ExternalReference::handle_scope_extensions_address();
475 const int kExtensionsOffset = 0;
476 const int kNextOffset = Offset(
477 ExternalReference::handle_scope_next_address(),
478 extensions_address);
479 const int kLimitOffset = Offset(
480 ExternalReference::handle_scope_limit_address(),
481 extensions_address);
482
483 // Push the number of extensions, smi-tagged so the gc will ignore it.
484 movq(kScratchRegister, extensions_address);
485 movq(scratch, Operand(kScratchRegister, kExtensionsOffset));
486 movq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0));
487 Integer32ToSmi(scratch, scratch);
488 push(scratch);
489 // Push next and limit pointers which will be wordsize aligned and
490 // hence automatically smi tagged.
491 push(Operand(kScratchRegister, kNextOffset));
492 push(Operand(kScratchRegister, kLimitOffset));
493}
494
495
496Object* MacroAssembler::PopHandleScopeHelper(Register saved,
497 Register scratch,
498 bool gc_allowed) {
499 ExternalReference extensions_address =
500 ExternalReference::handle_scope_extensions_address();
501 const int kExtensionsOffset = 0;
502 const int kNextOffset = Offset(
503 ExternalReference::handle_scope_next_address(),
504 extensions_address);
505 const int kLimitOffset = Offset(
506 ExternalReference::handle_scope_limit_address(),
507 extensions_address);
508
509 Object* result = NULL;
510 Label write_back;
511 movq(kScratchRegister, extensions_address);
512 cmpq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0));
513 j(equal, &write_back);
514 push(saved);
515 if (gc_allowed) {
516 CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
517 } else {
518 result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
519 if (result->IsFailure()) return result;
520 }
521 pop(saved);
522 movq(kScratchRegister, extensions_address);
523
524 bind(&write_back);
525 pop(Operand(kScratchRegister, kLimitOffset));
526 pop(Operand(kScratchRegister, kNextOffset));
527 pop(scratch);
528 SmiToInteger32(scratch, scratch);
529 movq(Operand(kScratchRegister, kExtensionsOffset), scratch);
530
531 return result;
532}
533
534
535void MacroAssembler::PopHandleScope(Register saved, Register scratch) {
536 PopHandleScopeHelper(saved, scratch, true);
537}
538
539
540Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) {
541 return PopHandleScopeHelper(saved, scratch, false);
542}
543
544
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000545void MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
546 int result_size) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000547 // Set the entry point and jump to the C entry runtime stub.
548 movq(rbx, ext);
ager@chromium.orga1645e22009-09-09 19:27:10 +0000549 CEntryStub ces(result_size);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000550 jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000551}
552
ager@chromium.orge2902be2009-06-08 12:21:35 +0000553
ager@chromium.org5c838252010-02-19 08:53:10 +0000554void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
555 // Calls are not allowed in some stubs.
556 ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000557
ager@chromium.org5c838252010-02-19 08:53:10 +0000558 // Rely on the assertion to check that the number of provided
559 // arguments match the expected number of arguments. Fake a
560 // parameter count to avoid emitting code to do the check.
561 ParameterCount expected(0);
562 GetBuiltinEntry(rdx, id);
563 InvokeCode(rdx, expected, expected, flag);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000564}
565
ager@chromium.org5c838252010-02-19 08:53:10 +0000566
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000567void MacroAssembler::GetBuiltinFunction(Register target,
568 Builtins::JavaScript id) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000569 // Load the builtins object into target register.
570 movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
571 movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000572 movq(target, FieldOperand(target,
573 JSBuiltinsObject::OffsetOfFunctionWithId(id)));
574}
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000575
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000576
577void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
578 ASSERT(!target.is(rdi));
ager@chromium.org5c838252010-02-19 08:53:10 +0000579 // Load the JavaScript builtin function from the builtins object.
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000580 GetBuiltinFunction(rdi, id);
581 movq(target, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000582}
583
584
ager@chromium.orge2902be2009-06-08 12:21:35 +0000585void MacroAssembler::Set(Register dst, int64_t x) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000586 if (x == 0) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000587 xorl(dst, dst);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000588 } else if (is_int32(x)) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000589 movq(dst, Immediate(static_cast<int32_t>(x)));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000590 } else if (is_uint32(x)) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000591 movl(dst, Immediate(static_cast<uint32_t>(x)));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000592 } else {
593 movq(dst, x, RelocInfo::NONE);
594 }
595}
596
ager@chromium.orge2902be2009-06-08 12:21:35 +0000597void MacroAssembler::Set(const Operand& dst, int64_t x) {
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000598 if (is_int32(x)) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000599 movq(dst, Immediate(static_cast<int32_t>(x)));
ager@chromium.orge2902be2009-06-08 12:21:35 +0000600 } else {
601 movq(kScratchRegister, x, RelocInfo::NONE);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000602 movq(dst, kScratchRegister);
ager@chromium.orge2902be2009-06-08 12:21:35 +0000603 }
ager@chromium.orge2902be2009-06-08 12:21:35 +0000604}
605
ager@chromium.org4af710e2009-09-15 12:20:11 +0000606// ----------------------------------------------------------------------------
607// Smi tagging, untagging and tag detection.
608
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000609Register MacroAssembler::GetSmiConstant(Smi* source) {
610 int value = source->value();
611 if (value == 0) {
612 xorl(kScratchRegister, kScratchRegister);
613 return kScratchRegister;
614 }
615 if (value == 1) {
616 return kSmiConstantRegister;
617 }
618 LoadSmiConstant(kScratchRegister, source);
619 return kScratchRegister;
620}
621
622void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
623 if (FLAG_debug_code) {
624 movq(dst,
625 reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)),
626 RelocInfo::NONE);
627 cmpq(dst, kSmiConstantRegister);
628 if (allow_stub_calls()) {
629 Assert(equal, "Uninitialized kSmiConstantRegister");
630 } else {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000631 NearLabel ok;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000632 j(equal, &ok);
633 int3();
634 bind(&ok);
635 }
636 }
637 if (source->value() == 0) {
638 xorl(dst, dst);
639 return;
640 }
641 int value = source->value();
642 bool negative = value < 0;
643 unsigned int uvalue = negative ? -value : value;
644
645 switch (uvalue) {
646 case 9:
647 lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_8, 0));
648 break;
649 case 8:
650 xorl(dst, dst);
651 lea(dst, Operand(dst, kSmiConstantRegister, times_8, 0));
652 break;
653 case 4:
654 xorl(dst, dst);
655 lea(dst, Operand(dst, kSmiConstantRegister, times_4, 0));
656 break;
657 case 5:
658 lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_4, 0));
659 break;
660 case 3:
661 lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_2, 0));
662 break;
663 case 2:
664 lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0));
665 break;
666 case 1:
667 movq(dst, kSmiConstantRegister);
668 break;
669 case 0:
670 UNREACHABLE();
671 return;
672 default:
673 movq(dst, reinterpret_cast<uint64_t>(source), RelocInfo::NONE);
674 return;
675 }
676 if (negative) {
677 neg(dst);
678 }
679}
680
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000681
ager@chromium.org4af710e2009-09-15 12:20:11 +0000682void MacroAssembler::Integer32ToSmi(Register dst, Register src) {
ager@chromium.org4af710e2009-09-15 12:20:11 +0000683 ASSERT_EQ(0, kSmiTag);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000684 if (!dst.is(src)) {
685 movl(dst, src);
ager@chromium.org4af710e2009-09-15 12:20:11 +0000686 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000687 shl(dst, Immediate(kSmiShift));
ager@chromium.org4af710e2009-09-15 12:20:11 +0000688}
689
690
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000691void MacroAssembler::Integer32ToSmiField(const Operand& dst, Register src) {
692 if (FLAG_debug_code) {
693 testb(dst, Immediate(0x01));
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000694 NearLabel ok;
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000695 j(zero, &ok);
696 if (allow_stub_calls()) {
697 Abort("Integer32ToSmiField writing to non-smi location");
698 } else {
699 int3();
700 }
701 bind(&ok);
702 }
703 ASSERT(kSmiShift % kBitsPerByte == 0);
704 movl(Operand(dst, kSmiShift / kBitsPerByte), src);
705}
706
707
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000708void MacroAssembler::Integer64PlusConstantToSmi(Register dst,
709 Register src,
710 int constant) {
711 if (dst.is(src)) {
712 addq(dst, Immediate(constant));
713 } else {
714 lea(dst, Operand(src, constant));
715 }
716 shl(dst, Immediate(kSmiShift));
ager@chromium.org4af710e2009-09-15 12:20:11 +0000717}
718
719
720void MacroAssembler::SmiToInteger32(Register dst, Register src) {
ager@chromium.org4af710e2009-09-15 12:20:11 +0000721 ASSERT_EQ(0, kSmiTag);
722 if (!dst.is(src)) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000723 movq(dst, src);
ager@chromium.org4af710e2009-09-15 12:20:11 +0000724 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000725 shr(dst, Immediate(kSmiShift));
ager@chromium.org4af710e2009-09-15 12:20:11 +0000726}
727
728
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000729void MacroAssembler::SmiToInteger32(Register dst, const Operand& src) {
730 movl(dst, Operand(src, kSmiShift / kBitsPerByte));
731}
732
733
ager@chromium.org4af710e2009-09-15 12:20:11 +0000734void MacroAssembler::SmiToInteger64(Register dst, Register src) {
ager@chromium.org4af710e2009-09-15 12:20:11 +0000735 ASSERT_EQ(0, kSmiTag);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000736 if (!dst.is(src)) {
737 movq(dst, src);
738 }
739 sar(dst, Immediate(kSmiShift));
740}
741
742
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000743void MacroAssembler::SmiToInteger64(Register dst, const Operand& src) {
744 movsxlq(dst, Operand(src, kSmiShift / kBitsPerByte));
745}
746
747
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000748void MacroAssembler::SmiTest(Register src) {
749 testq(src, src);
750}
751
752
753void MacroAssembler::SmiCompare(Register dst, Register src) {
754 cmpq(dst, src);
755}
756
757
758void MacroAssembler::SmiCompare(Register dst, Smi* src) {
759 ASSERT(!dst.is(kScratchRegister));
760 if (src->value() == 0) {
761 testq(dst, dst);
762 } else {
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000763 Register constant_reg = GetSmiConstant(src);
764 cmpq(dst, constant_reg);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000765 }
766}
767
768
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000769void MacroAssembler::SmiCompare(Register dst, const Operand& src) {
ager@chromium.orgac091b72010-05-05 07:34:42 +0000770 cmpq(dst, src);
771}
772
773
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000774void MacroAssembler::SmiCompare(const Operand& dst, Register src) {
775 cmpq(dst, src);
776}
777
778
779void MacroAssembler::SmiCompare(const Operand& dst, Smi* src) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000780 cmpl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(src->value()));
ager@chromium.org4af710e2009-09-15 12:20:11 +0000781}
782
783
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000784void MacroAssembler::SmiCompareInteger32(const Operand& dst, Register src) {
785 cmpl(Operand(dst, kSmiShift / kBitsPerByte), src);
786}
787
788
ager@chromium.org4af710e2009-09-15 12:20:11 +0000789void MacroAssembler::PositiveSmiTimesPowerOfTwoToInteger64(Register dst,
790 Register src,
791 int power) {
792 ASSERT(power >= 0);
793 ASSERT(power < 64);
794 if (power == 0) {
795 SmiToInteger64(dst, src);
796 return;
797 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000798 if (!dst.is(src)) {
799 movq(dst, src);
800 }
801 if (power < kSmiShift) {
802 sar(dst, Immediate(kSmiShift - power));
803 } else if (power > kSmiShift) {
804 shl(dst, Immediate(power - kSmiShift));
ager@chromium.org4af710e2009-09-15 12:20:11 +0000805 }
806}
807
808
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000809void MacroAssembler::PositiveSmiDivPowerOfTwoToInteger32(Register dst,
810 Register src,
811 int power) {
812 ASSERT((0 <= power) && (power < 32));
813 if (dst.is(src)) {
814 shr(dst, Immediate(power + kSmiShift));
815 } else {
816 UNIMPLEMENTED(); // Not used.
817 }
818}
819
820
ager@chromium.org4af710e2009-09-15 12:20:11 +0000821Condition MacroAssembler::CheckSmi(Register src) {
ager@chromium.org4af710e2009-09-15 12:20:11 +0000822 ASSERT_EQ(0, kSmiTag);
823 testb(src, Immediate(kSmiTagMask));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000824 return zero;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000825}
826
827
828Condition MacroAssembler::CheckPositiveSmi(Register src) {
829 ASSERT_EQ(0, kSmiTag);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000830 // Make mask 0x8000000000000001 and test that both bits are zero.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000831 movq(kScratchRegister, src);
832 rol(kScratchRegister, Immediate(1));
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000833 testb(kScratchRegister, Immediate(3));
ager@chromium.org4af710e2009-09-15 12:20:11 +0000834 return zero;
835}
836
837
ager@chromium.org4af710e2009-09-15 12:20:11 +0000838Condition MacroAssembler::CheckBothSmi(Register first, Register second) {
839 if (first.is(second)) {
840 return CheckSmi(first);
841 }
lrn@chromium.org32d961d2010-06-30 09:09:34 +0000842 ASSERT(kSmiTag == 0 && kHeapObjectTag == 1 && kHeapObjectTagMask == 3);
843 leal(kScratchRegister, Operand(first, second, times_1, 0));
844 testb(kScratchRegister, Immediate(0x03));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000845 return zero;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000846}
847
848
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000849Condition MacroAssembler::CheckBothPositiveSmi(Register first,
850 Register second) {
851 if (first.is(second)) {
852 return CheckPositiveSmi(first);
853 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +0000854 movq(kScratchRegister, first);
855 or_(kScratchRegister, second);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000856 rol(kScratchRegister, Immediate(1));
857 testl(kScratchRegister, Immediate(0x03));
858 return zero;
859}
860
861
lrn@chromium.orgc4e51ac2010-08-09 09:47:21 +0000862Condition MacroAssembler::CheckEitherSmi(Register first,
863 Register second,
864 Register scratch) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000865 if (first.is(second)) {
866 return CheckSmi(first);
867 }
lrn@chromium.orgc4e51ac2010-08-09 09:47:21 +0000868 if (scratch.is(second)) {
869 andl(scratch, first);
870 } else {
871 if (!scratch.is(first)) {
872 movl(scratch, first);
873 }
874 andl(scratch, second);
875 }
876 testb(scratch, Immediate(kSmiTagMask));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000877 return zero;
878}
879
880
ager@chromium.org4af710e2009-09-15 12:20:11 +0000881Condition MacroAssembler::CheckIsMinSmi(Register src) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000882 ASSERT(!src.is(kScratchRegister));
883 // If we overflow by subtracting one, it's the minimal smi value.
884 cmpq(src, kSmiConstantRegister);
885 return overflow;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000886}
887
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000888
ager@chromium.org4af710e2009-09-15 12:20:11 +0000889Condition MacroAssembler::CheckInteger32ValidSmiValue(Register src) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000890 // A 32-bit integer value can always be converted to a smi.
891 return always;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000892}
893
894
ager@chromium.org3811b432009-10-28 14:53:37 +0000895Condition MacroAssembler::CheckUInteger32ValidSmiValue(Register src) {
896 // An unsigned 32-bit integer value is valid as long as the high bit
897 // is not set.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000898 testl(src, src);
899 return positive;
ager@chromium.org3811b432009-10-28 14:53:37 +0000900}
901
902
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000903void MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) {
904 if (constant->value() == 0) {
905 if (!dst.is(src)) {
906 movq(dst, src);
907 }
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000908 return;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000909 } else if (dst.is(src)) {
910 ASSERT(!dst.is(kScratchRegister));
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000911 switch (constant->value()) {
912 case 1:
913 addq(dst, kSmiConstantRegister);
914 return;
915 case 2:
916 lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
917 return;
918 case 4:
919 lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
920 return;
921 case 8:
922 lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
923 return;
924 default:
925 Register constant_reg = GetSmiConstant(constant);
926 addq(dst, constant_reg);
927 return;
928 }
ager@chromium.org4af710e2009-09-15 12:20:11 +0000929 } else {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000930 switch (constant->value()) {
931 case 1:
932 lea(dst, Operand(src, kSmiConstantRegister, times_1, 0));
933 return;
934 case 2:
935 lea(dst, Operand(src, kSmiConstantRegister, times_2, 0));
936 return;
937 case 4:
938 lea(dst, Operand(src, kSmiConstantRegister, times_4, 0));
939 return;
940 case 8:
941 lea(dst, Operand(src, kSmiConstantRegister, times_8, 0));
942 return;
943 default:
944 LoadSmiConstant(dst, constant);
945 addq(dst, src);
946 return;
947 }
ager@chromium.org4af710e2009-09-15 12:20:11 +0000948 }
949}
950
951
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000952void MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
953 if (constant->value() != 0) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000954 addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value()));
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000955 }
956}
957
958
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000959void MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) {
960 if (constant->value() == 0) {
ager@chromium.org4af710e2009-09-15 12:20:11 +0000961 if (!dst.is(src)) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000962 movq(dst, src);
ager@chromium.org4af710e2009-09-15 12:20:11 +0000963 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000964 } else if (dst.is(src)) {
965 ASSERT(!dst.is(kScratchRegister));
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000966 Register constant_reg = GetSmiConstant(constant);
967 subq(dst, constant_reg);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000968 } else {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000969 if (constant->value() == Smi::kMinValue) {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000970 LoadSmiConstant(dst, constant);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000971 // Adding and subtracting the min-value gives the same result, it only
972 // differs on the overflow bit, which we don't check here.
973 addq(dst, src);
ager@chromium.org4af710e2009-09-15 12:20:11 +0000974 } else {
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000975 // Subtract by adding the negation.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000976 LoadSmiConstant(dst, Smi::FromInt(-constant->value()));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000977 addq(dst, src);
ager@chromium.org4af710e2009-09-15 12:20:11 +0000978 }
979 }
980}
981
982
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000983void MacroAssembler::SmiAdd(Register dst,
984 Register src1,
985 Register src2) {
986 // No overflow checking. Use only when it's known that
987 // overflowing is impossible.
988 ASSERT(!dst.is(src2));
989 if (dst.is(src1)) {
990 addq(dst, src2);
ager@chromium.org4af710e2009-09-15 12:20:11 +0000991 } else {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000992 movq(dst, src1);
993 addq(dst, src2);
ager@chromium.org4af710e2009-09-15 12:20:11 +0000994 }
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000995 Assert(no_overflow, "Smi addition overflow");
ager@chromium.org4af710e2009-09-15 12:20:11 +0000996}
997
998
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000999void MacroAssembler::SmiSub(Register dst, Register src1, Register src2) {
1000 // No overflow checking. Use only when it's known that
1001 // overflowing is impossible (e.g., subtracting two positive smis).
1002 ASSERT(!dst.is(src2));
1003 if (dst.is(src1)) {
1004 subq(dst, src2);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001005 } else {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001006 movq(dst, src1);
1007 subq(dst, src2);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001008 }
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001009 Assert(no_overflow, "Smi subtraction overflow");
ager@chromium.org4af710e2009-09-15 12:20:11 +00001010}
1011
1012
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001013void MacroAssembler::SmiSub(Register dst,
ager@chromium.org4af710e2009-09-15 12:20:11 +00001014 Register src1,
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001015 const Operand& src2) {
1016 // No overflow checking. Use only when it's known that
1017 // overflowing is impossible (e.g., subtracting two positive smis).
1018 if (dst.is(src1)) {
1019 subq(dst, src2);
1020 } else {
1021 movq(dst, src1);
1022 subq(dst, src2);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001023 }
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001024 Assert(no_overflow, "Smi subtraction overflow");
ager@chromium.org4af710e2009-09-15 12:20:11 +00001025}
1026
1027
1028void MacroAssembler::SmiNot(Register dst, Register src) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001029 ASSERT(!dst.is(kScratchRegister));
1030 ASSERT(!src.is(kScratchRegister));
1031 // Set tag and padding bits before negating, so that they are zero afterwards.
1032 movl(kScratchRegister, Immediate(~0));
ager@chromium.org4af710e2009-09-15 12:20:11 +00001033 if (dst.is(src)) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001034 xor_(dst, kScratchRegister);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001035 } else {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001036 lea(dst, Operand(src, kScratchRegister, times_1, 0));
ager@chromium.org4af710e2009-09-15 12:20:11 +00001037 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001038 not_(dst);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001039}
1040
1041
1042void MacroAssembler::SmiAnd(Register dst, Register src1, Register src2) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001043 ASSERT(!dst.is(src2));
ager@chromium.org4af710e2009-09-15 12:20:11 +00001044 if (!dst.is(src1)) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001045 movq(dst, src1);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001046 }
1047 and_(dst, src2);
1048}
1049
1050
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001051void MacroAssembler::SmiAndConstant(Register dst, Register src, Smi* constant) {
1052 if (constant->value() == 0) {
1053 xor_(dst, dst);
1054 } else if (dst.is(src)) {
1055 ASSERT(!dst.is(kScratchRegister));
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001056 Register constant_reg = GetSmiConstant(constant);
1057 and_(dst, constant_reg);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001058 } else {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001059 LoadSmiConstant(dst, constant);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001060 and_(dst, src);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001061 }
ager@chromium.org4af710e2009-09-15 12:20:11 +00001062}
1063
1064
1065void MacroAssembler::SmiOr(Register dst, Register src1, Register src2) {
1066 if (!dst.is(src1)) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001067 movq(dst, src1);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001068 }
1069 or_(dst, src2);
1070}
1071
1072
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001073void MacroAssembler::SmiOrConstant(Register dst, Register src, Smi* constant) {
1074 if (dst.is(src)) {
1075 ASSERT(!dst.is(kScratchRegister));
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001076 Register constant_reg = GetSmiConstant(constant);
1077 or_(dst, constant_reg);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001078 } else {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001079 LoadSmiConstant(dst, constant);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001080 or_(dst, src);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001081 }
ager@chromium.org4af710e2009-09-15 12:20:11 +00001082}
1083
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001084
ager@chromium.org4af710e2009-09-15 12:20:11 +00001085void MacroAssembler::SmiXor(Register dst, Register src1, Register src2) {
1086 if (!dst.is(src1)) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001087 movq(dst, src1);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001088 }
1089 xor_(dst, src2);
1090}
1091
1092
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001093void MacroAssembler::SmiXorConstant(Register dst, Register src, Smi* constant) {
1094 if (dst.is(src)) {
1095 ASSERT(!dst.is(kScratchRegister));
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001096 Register constant_reg = GetSmiConstant(constant);
1097 xor_(dst, constant_reg);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001098 } else {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001099 LoadSmiConstant(dst, constant);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001100 xor_(dst, src);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001101 }
ager@chromium.org4af710e2009-09-15 12:20:11 +00001102}
1103
1104
ager@chromium.org4af710e2009-09-15 12:20:11 +00001105void MacroAssembler::SmiShiftArithmeticRightConstant(Register dst,
1106 Register src,
1107 int shift_value) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001108 ASSERT(is_uint5(shift_value));
ager@chromium.org4af710e2009-09-15 12:20:11 +00001109 if (shift_value > 0) {
1110 if (dst.is(src)) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001111 sar(dst, Immediate(shift_value + kSmiShift));
1112 shl(dst, Immediate(kSmiShift));
ager@chromium.org4af710e2009-09-15 12:20:11 +00001113 } else {
1114 UNIMPLEMENTED(); // Not used.
1115 }
1116 }
1117}
1118
1119
ager@chromium.org4af710e2009-09-15 12:20:11 +00001120void MacroAssembler::SmiShiftLeftConstant(Register dst,
1121 Register src,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001122 int shift_value) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001123 if (!dst.is(src)) {
1124 movq(dst, src);
1125 }
1126 if (shift_value > 0) {
1127 shl(dst, Immediate(shift_value));
ager@chromium.org4af710e2009-09-15 12:20:11 +00001128 }
1129}
1130
1131
1132void MacroAssembler::SmiShiftLeft(Register dst,
1133 Register src1,
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001134 Register src2) {
ager@chromium.org4af710e2009-09-15 12:20:11 +00001135 ASSERT(!dst.is(rcx));
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001136 NearLabel result_ok;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001137 // Untag shift amount.
1138 if (!dst.is(src1)) {
1139 movq(dst, src1);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001140 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001141 SmiToInteger32(rcx, src2);
1142 // Shift amount specified by lower 5 bits, not six as the shl opcode.
1143 and_(rcx, Immediate(0x1f));
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001144 shl_cl(dst);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001145}
1146
1147
ager@chromium.org4af710e2009-09-15 12:20:11 +00001148void MacroAssembler::SmiShiftArithmeticRight(Register dst,
1149 Register src1,
1150 Register src2) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001151 ASSERT(!dst.is(kScratchRegister));
1152 ASSERT(!src1.is(kScratchRegister));
1153 ASSERT(!src2.is(kScratchRegister));
ager@chromium.org4af710e2009-09-15 12:20:11 +00001154 ASSERT(!dst.is(rcx));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001155 if (src1.is(rcx)) {
1156 movq(kScratchRegister, src1);
1157 } else if (src2.is(rcx)) {
1158 movq(kScratchRegister, src2);
1159 }
1160 if (!dst.is(src1)) {
1161 movq(dst, src1);
1162 }
ager@chromium.org4af710e2009-09-15 12:20:11 +00001163 SmiToInteger32(rcx, src2);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001164 orl(rcx, Immediate(kSmiShift));
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001165 sar_cl(dst); // Shift 32 + original rcx & 0x1f.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001166 shl(dst, Immediate(kSmiShift));
1167 if (src1.is(rcx)) {
1168 movq(src1, kScratchRegister);
1169 } else if (src2.is(rcx)) {
1170 movq(src2, kScratchRegister);
1171 }
ager@chromium.org4af710e2009-09-15 12:20:11 +00001172}
1173
1174
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001175SmiIndex MacroAssembler::SmiToIndex(Register dst,
1176 Register src,
1177 int shift) {
ager@chromium.org4af710e2009-09-15 12:20:11 +00001178 ASSERT(is_uint6(shift));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001179 // There is a possible optimization if shift is in the range 60-63, but that
1180 // will (and must) never happen.
1181 if (!dst.is(src)) {
1182 movq(dst, src);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001183 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001184 if (shift < kSmiShift) {
1185 sar(dst, Immediate(kSmiShift - shift));
1186 } else {
1187 shl(dst, Immediate(shift - kSmiShift));
ager@chromium.org4af710e2009-09-15 12:20:11 +00001188 }
ager@chromium.org4af710e2009-09-15 12:20:11 +00001189 return SmiIndex(dst, times_1);
1190}
1191
ager@chromium.org4af710e2009-09-15 12:20:11 +00001192SmiIndex MacroAssembler::SmiToNegativeIndex(Register dst,
1193 Register src,
1194 int shift) {
1195 // Register src holds a positive smi.
1196 ASSERT(is_uint6(shift));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001197 if (!dst.is(src)) {
1198 movq(dst, src);
ager@chromium.org4af710e2009-09-15 12:20:11 +00001199 }
ager@chromium.org4af710e2009-09-15 12:20:11 +00001200 neg(dst);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001201 if (shift < kSmiShift) {
1202 sar(dst, Immediate(kSmiShift - shift));
1203 } else {
1204 shl(dst, Immediate(shift - kSmiShift));
1205 }
ager@chromium.org4af710e2009-09-15 12:20:11 +00001206 return SmiIndex(dst, times_1);
1207}
1208
1209
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001210void MacroAssembler::Move(Register dst, Handle<Object> source) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001211 ASSERT(!source->IsFailure());
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001212 if (source->IsSmi()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001213 Move(dst, Smi::cast(*source));
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001214 } else {
1215 movq(dst, source, RelocInfo::EMBEDDED_OBJECT);
1216 }
1217}
1218
1219
1220void MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001221 ASSERT(!source->IsFailure());
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001222 if (source->IsSmi()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001223 Move(dst, Smi::cast(*source));
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001224 } else {
1225 movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
1226 movq(dst, kScratchRegister);
1227 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001228}
1229
1230
1231void MacroAssembler::Cmp(Register dst, Handle<Object> source) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001232 if (source->IsSmi()) {
1233 SmiCompare(dst, Smi::cast(*source));
1234 } else {
1235 Move(kScratchRegister, source);
1236 cmpq(dst, kScratchRegister);
1237 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001238}
1239
1240
ager@chromium.org3e875802009-06-29 08:26:34 +00001241void MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001242 if (source->IsSmi()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001243 SmiCompare(dst, Smi::cast(*source));
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001244 } else {
1245 ASSERT(source->IsHeapObject());
1246 movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
1247 cmpq(dst, kScratchRegister);
1248 }
ager@chromium.org3e875802009-06-29 08:26:34 +00001249}
1250
1251
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001252void MacroAssembler::Push(Handle<Object> source) {
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001253 if (source->IsSmi()) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001254 Push(Smi::cast(*source));
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001255 } else {
1256 ASSERT(source->IsHeapObject());
1257 movq(kScratchRegister, source, RelocInfo::EMBEDDED_OBJECT);
1258 push(kScratchRegister);
1259 }
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001260}
1261
1262
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001263void MacroAssembler::Push(Smi* source) {
ager@chromium.org3811b432009-10-28 14:53:37 +00001264 intptr_t smi = reinterpret_cast<intptr_t>(source);
1265 if (is_int32(smi)) {
1266 push(Immediate(static_cast<int32_t>(smi)));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001267 } else {
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001268 Register constant = GetSmiConstant(source);
1269 push(constant);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001270 }
1271}
1272
1273
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001274void MacroAssembler::Drop(int stack_elements) {
1275 if (stack_elements > 0) {
1276 addq(rsp, Immediate(stack_elements * kPointerSize));
1277 }
1278}
1279
1280
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001281void MacroAssembler::Test(const Operand& src, Smi* source) {
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00001282 testl(Operand(src, kIntSize), Immediate(source->value()));
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +00001283}
1284
1285
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001286void MacroAssembler::Jump(ExternalReference ext) {
1287 movq(kScratchRegister, ext);
1288 jmp(kScratchRegister);
1289}
1290
1291
1292void MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) {
1293 movq(kScratchRegister, destination, rmode);
1294 jmp(kScratchRegister);
1295}
1296
1297
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001298void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001299 // TODO(X64): Inline this
1300 jmp(code_object, rmode);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001301}
1302
1303
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001304void MacroAssembler::Call(ExternalReference ext) {
1305 movq(kScratchRegister, ext);
1306 call(kScratchRegister);
1307}
1308
1309
1310void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
1311 movq(kScratchRegister, destination, rmode);
1312 call(kScratchRegister);
1313}
1314
1315
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001316void MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001317 ASSERT(RelocInfo::IsCodeTarget(rmode));
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001318 call(code_object, rmode);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001319}
1320
1321
ager@chromium.orge2902be2009-06-08 12:21:35 +00001322void MacroAssembler::PushTryHandler(CodeLocation try_location,
1323 HandlerType type) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001324 // Adjust this code if not the case.
1325 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
1326
1327 // The pc (return address) is already on TOS. This code pushes state,
1328 // frame pointer and current handler. Check that they are expected
1329 // next on the stack, in that order.
ager@chromium.orge2902be2009-06-08 12:21:35 +00001330 ASSERT_EQ(StackHandlerConstants::kStateOffset,
1331 StackHandlerConstants::kPCOffset - kPointerSize);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001332 ASSERT_EQ(StackHandlerConstants::kFPOffset,
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001333 StackHandlerConstants::kStateOffset - kPointerSize);
1334 ASSERT_EQ(StackHandlerConstants::kNextOffset,
ager@chromium.orge2902be2009-06-08 12:21:35 +00001335 StackHandlerConstants::kFPOffset - kPointerSize);
1336
1337 if (try_location == IN_JAVASCRIPT) {
1338 if (type == TRY_CATCH_HANDLER) {
1339 push(Immediate(StackHandler::TRY_CATCH));
1340 } else {
1341 push(Immediate(StackHandler::TRY_FINALLY));
1342 }
ager@chromium.orge2902be2009-06-08 12:21:35 +00001343 push(rbp);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001344 } else {
1345 ASSERT(try_location == IN_JS_ENTRY);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001346 // The frame pointer does not point to a JS frame so we save NULL
1347 // for rbp. We expect the code throwing an exception to check rbp
1348 // before dereferencing it to restore the context.
ager@chromium.orge2902be2009-06-08 12:21:35 +00001349 push(Immediate(StackHandler::ENTRY));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001350 push(Immediate(0)); // NULL frame pointer.
ager@chromium.orge2902be2009-06-08 12:21:35 +00001351 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001352 // Save the current handler.
ager@chromium.orge2902be2009-06-08 12:21:35 +00001353 movq(kScratchRegister, ExternalReference(Top::k_handler_address));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001354 push(Operand(kScratchRegister, 0));
ager@chromium.orge2902be2009-06-08 12:21:35 +00001355 // Link this handler.
1356 movq(Operand(kScratchRegister, 0), rsp);
1357}
1358
1359
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001360void MacroAssembler::PopTryHandler() {
1361 ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
1362 // Unlink this handler.
1363 movq(kScratchRegister, ExternalReference(Top::k_handler_address));
1364 pop(Operand(kScratchRegister, 0));
1365 // Remove the remaining fields.
1366 addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
1367}
1368
1369
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001370void MacroAssembler::Ret() {
1371 ret(0);
1372}
1373
1374
ager@chromium.org3e875802009-06-29 08:26:34 +00001375void MacroAssembler::FCmp() {
ager@chromium.org3811b432009-10-28 14:53:37 +00001376 fucomip();
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001377 fstp(0);
ager@chromium.org3e875802009-06-29 08:26:34 +00001378}
1379
1380
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001381void MacroAssembler::CmpObjectType(Register heap_object,
1382 InstanceType type,
1383 Register map) {
1384 movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
1385 CmpInstanceType(map, type);
1386}
1387
1388
1389void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
1390 cmpb(FieldOperand(map, Map::kInstanceTypeOffset),
1391 Immediate(static_cast<int8_t>(type)));
1392}
1393
1394
ager@chromium.org5c838252010-02-19 08:53:10 +00001395void MacroAssembler::CheckMap(Register obj,
1396 Handle<Map> map,
1397 Label* fail,
1398 bool is_heap_object) {
1399 if (!is_heap_object) {
1400 JumpIfSmi(obj, fail);
1401 }
1402 Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
1403 j(not_equal, fail);
1404}
1405
1406
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001407void MacroAssembler::AbortIfNotNumber(Register object) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001408 NearLabel ok;
ager@chromium.org5c838252010-02-19 08:53:10 +00001409 Condition is_smi = CheckSmi(object);
1410 j(is_smi, &ok);
1411 Cmp(FieldOperand(object, HeapObject::kMapOffset),
1412 Factory::heap_number_map());
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001413 Assert(equal, "Operand not a number");
ager@chromium.org5c838252010-02-19 08:53:10 +00001414 bind(&ok);
1415}
1416
1417
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001418void MacroAssembler::AbortIfSmi(Register object) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001419 NearLabel ok;
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001420 Condition is_smi = CheckSmi(object);
1421 Assert(NegateCondition(is_smi), "Operand is a smi");
1422}
1423
1424
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001425void MacroAssembler::AbortIfNotSmi(Register object) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001426 NearLabel ok;
lrn@chromium.org25156de2010-04-06 13:10:27 +00001427 Condition is_smi = CheckSmi(object);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001428 Assert(is_smi, "Operand is not a smi");
lrn@chromium.org25156de2010-04-06 13:10:27 +00001429}
1430
1431
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +00001432void MacroAssembler::AbortIfNotRootValue(Register src,
1433 Heap::RootListIndex root_value_index,
1434 const char* message) {
1435 ASSERT(!src.is(kScratchRegister));
1436 LoadRoot(kScratchRegister, root_value_index);
1437 cmpq(src, kScratchRegister);
1438 Check(equal, message);
1439}
1440
1441
1442
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001443Condition MacroAssembler::IsObjectStringType(Register heap_object,
1444 Register map,
1445 Register instance_type) {
1446 movq(map, FieldOperand(heap_object, HeapObject::kMapOffset));
1447 movzxbl(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
1448 ASSERT(kNotStringTag != 0);
1449 testb(instance_type, Immediate(kIsNotStringMask));
1450 return zero;
1451}
1452
1453
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001454void MacroAssembler::TryGetFunctionPrototype(Register function,
1455 Register result,
1456 Label* miss) {
1457 // Check that the receiver isn't a smi.
1458 testl(function, Immediate(kSmiTagMask));
1459 j(zero, miss);
1460
1461 // Check that the function really is a function.
1462 CmpObjectType(function, JS_FUNCTION_TYPE, result);
1463 j(not_equal, miss);
1464
1465 // Make sure that the function has an instance prototype.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001466 NearLabel non_instance;
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001467 testb(FieldOperand(result, Map::kBitFieldOffset),
1468 Immediate(1 << Map::kHasNonInstancePrototype));
1469 j(not_zero, &non_instance);
1470
1471 // Get the prototype or initial map from the function.
1472 movq(result,
1473 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
1474
1475 // If the prototype or initial map is the hole, don't return it and
1476 // simply miss the cache instead. This will allow us to allocate a
1477 // prototype object on-demand in the runtime system.
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001478 CompareRoot(result, Heap::kTheHoleValueRootIndex);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001479 j(equal, miss);
1480
1481 // If the function does not have an initial map, we're done.
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001482 NearLabel done;
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001483 CmpObjectType(result, MAP_TYPE, kScratchRegister);
1484 j(not_equal, &done);
1485
1486 // Get the prototype from the initial map.
1487 movq(result, FieldOperand(result, Map::kPrototypeOffset));
1488 jmp(&done);
1489
1490 // Non-instance prototype: Fetch prototype from constructor field
1491 // in initial map.
1492 bind(&non_instance);
1493 movq(result, FieldOperand(result, Map::kConstructorOffset));
1494
1495 // All done.
1496 bind(&done);
1497}
1498
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001499
1500void MacroAssembler::SetCounter(StatsCounter* counter, int value) {
1501 if (FLAG_native_code_counters && counter->Enabled()) {
1502 movq(kScratchRegister, ExternalReference(counter));
1503 movl(Operand(kScratchRegister, 0), Immediate(value));
1504 }
1505}
1506
1507
1508void MacroAssembler::IncrementCounter(StatsCounter* counter, int value) {
1509 ASSERT(value > 0);
1510 if (FLAG_native_code_counters && counter->Enabled()) {
1511 movq(kScratchRegister, ExternalReference(counter));
1512 Operand operand(kScratchRegister, 0);
1513 if (value == 1) {
1514 incl(operand);
1515 } else {
1516 addl(operand, Immediate(value));
1517 }
1518 }
1519}
1520
1521
1522void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) {
1523 ASSERT(value > 0);
1524 if (FLAG_native_code_counters && counter->Enabled()) {
1525 movq(kScratchRegister, ExternalReference(counter));
1526 Operand operand(kScratchRegister, 0);
1527 if (value == 1) {
1528 decl(operand);
1529 } else {
1530 subl(operand, Immediate(value));
1531 }
1532 }
1533}
1534
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001535
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001536#ifdef ENABLE_DEBUGGER_SUPPORT
ager@chromium.org5c838252010-02-19 08:53:10 +00001537void MacroAssembler::DebugBreak() {
1538 ASSERT(allow_stub_calls());
1539 xor_(rax, rax); // no arguments
1540 movq(rbx, ExternalReference(Runtime::kDebugBreak));
1541 CEntryStub ces(1);
1542 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK);
ager@chromium.org3e875802009-06-29 08:26:34 +00001543}
ager@chromium.org5c838252010-02-19 08:53:10 +00001544#endif // ENABLE_DEBUGGER_SUPPORT
ager@chromium.org3e875802009-06-29 08:26:34 +00001545
1546
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001547void MacroAssembler::InvokeCode(Register code,
1548 const ParameterCount& expected,
1549 const ParameterCount& actual,
1550 InvokeFlag flag) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001551 NearLabel done;
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001552 InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag);
1553 if (flag == CALL_FUNCTION) {
1554 call(code);
1555 } else {
1556 ASSERT(flag == JUMP_FUNCTION);
1557 jmp(code);
1558 }
1559 bind(&done);
1560}
1561
1562
1563void MacroAssembler::InvokeCode(Handle<Code> code,
1564 const ParameterCount& expected,
1565 const ParameterCount& actual,
1566 RelocInfo::Mode rmode,
1567 InvokeFlag flag) {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +00001568 NearLabel done;
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001569 Register dummy = rax;
1570 InvokePrologue(expected, actual, code, dummy, &done, flag);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001571 if (flag == CALL_FUNCTION) {
ager@chromium.org3e875802009-06-29 08:26:34 +00001572 Call(code, rmode);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001573 } else {
1574 ASSERT(flag == JUMP_FUNCTION);
ager@chromium.org3e875802009-06-29 08:26:34 +00001575 Jump(code, rmode);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001576 }
1577 bind(&done);
1578}
1579
1580
1581void MacroAssembler::InvokeFunction(Register function,
1582 const ParameterCount& actual,
1583 InvokeFlag flag) {
1584 ASSERT(function.is(rdi));
1585 movq(rdx, FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
1586 movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
ager@chromium.org3e875802009-06-29 08:26:34 +00001587 movsxlq(rbx,
1588 FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001589 // Advances rdx to the end of the Code object header, to the start of
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001590 // the executable code.
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00001591 movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001592
1593 ParameterCount expected(rbx);
1594 InvokeCode(rdx, expected, actual, flag);
1595}
1596
1597
ager@chromium.org5c838252010-02-19 08:53:10 +00001598void MacroAssembler::InvokeFunction(JSFunction* function,
1599 const ParameterCount& actual,
1600 InvokeFlag flag) {
1601 ASSERT(function->is_compiled());
1602 // Get the function and setup the context.
1603 Move(rdi, Handle<JSFunction>(function));
1604 movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
1605
1606 // Invoke the cached code.
1607 Handle<Code> code(function->code());
1608 ParameterCount expected(function->shared()->formal_parameter_count());
1609 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag);
1610}
1611
1612
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001613void MacroAssembler::EnterFrame(StackFrame::Type type) {
1614 push(rbp);
1615 movq(rbp, rsp);
1616 push(rsi); // Context.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001617 Push(Smi::FromInt(type));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001618 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
1619 push(kScratchRegister);
1620 if (FLAG_debug_code) {
1621 movq(kScratchRegister,
1622 Factory::undefined_value(),
1623 RelocInfo::EMBEDDED_OBJECT);
1624 cmpq(Operand(rsp, 0), kScratchRegister);
1625 Check(not_equal, "code object not properly patched");
1626 }
1627}
1628
1629
1630void MacroAssembler::LeaveFrame(StackFrame::Type type) {
1631 if (FLAG_debug_code) {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001632 Move(kScratchRegister, Smi::FromInt(type));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001633 cmpq(Operand(rbp, StandardFrameConstants::kMarkerOffset), kScratchRegister);
1634 Check(equal, "stack frame types must match");
1635 }
1636 movq(rsp, rbp);
1637 pop(rbp);
1638}
1639
1640
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001641void MacroAssembler::EnterExitFramePrologue(bool save_rax) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001642 // Setup the frame structure on the stack.
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001643 // All constants are relative to the frame pointer of the exit frame.
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001644 ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
1645 ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
1646 ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
1647 push(rbp);
1648 movq(rbp, rsp);
1649
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001650 // Reserve room for entry stack pointer and push the code object.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001651 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
ager@chromium.org5c838252010-02-19 08:53:10 +00001652 push(Immediate(0)); // Saved entry sp, patched before call.
1653 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
1654 push(kScratchRegister); // Accessed from EditFrame::code_slot.
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001655
1656 // Save the frame pointer and the context in top.
1657 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
1658 ExternalReference context_address(Top::k_context_address);
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001659 if (save_rax) {
1660 movq(r14, rax); // Backup rax before we use it.
1661 }
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001662
1663 movq(rax, rbp);
1664 store_rax(c_entry_fp_address);
1665 movq(rax, rsi);
1666 store_rax(context_address);
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001667}
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001668
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001669void MacroAssembler::EnterExitFrameEpilogue(int result_size,
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001670 int argc) {
ager@chromium.orga1645e22009-09-09 19:27:10 +00001671#ifdef _WIN64
1672 // Reserve space on stack for result and argument structures, if necessary.
1673 int result_stack_space = (result_size < 2) ? 0 : result_size * kPointerSize;
1674 // Reserve space for the Arguments object. The Windows 64-bit ABI
1675 // requires us to pass this structure as a pointer to its location on
1676 // the stack. The structure contains 2 values.
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001677 int argument_stack_space = argc * kPointerSize;
ager@chromium.orga1645e22009-09-09 19:27:10 +00001678 // We also need backing space for 4 parameters, even though
1679 // we only pass one or two parameter, and it is in a register.
1680 int argument_mirror_space = 4 * kPointerSize;
1681 int total_stack_space =
1682 argument_mirror_space + argument_stack_space + result_stack_space;
1683 subq(rsp, Immediate(total_stack_space));
1684#endif
1685
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001686 // Get the required frame alignment for the OS.
1687 static const int kFrameAlignment = OS::ActivationFrameAlignment();
1688 if (kFrameAlignment > 0) {
1689 ASSERT(IsPowerOf2(kFrameAlignment));
1690 movq(kScratchRegister, Immediate(-kFrameAlignment));
1691 and_(rsp, kScratchRegister);
1692 }
1693
1694 // Patch the saved entry sp.
1695 movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
1696}
1697
1698
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001699void MacroAssembler::EnterExitFrame(int result_size) {
1700 EnterExitFramePrologue(true);
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001701
1702 // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
1703 // so it must be retained across the C-call.
1704 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
1705 lea(r12, Operand(rbp, r14, times_pointer_size, offset));
1706
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001707 EnterExitFrameEpilogue(result_size, 2);
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001708}
1709
1710
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001711void MacroAssembler::EnterApiExitFrame(int stack_space,
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001712 int argc,
1713 int result_size) {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001714 EnterExitFramePrologue(false);
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001715
1716 // Setup argv in callee-saved register r12. It is reused in LeaveExitFrame,
1717 // so it must be retained across the C-call.
1718 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
1719 lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset));
1720
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001721 EnterExitFrameEpilogue(result_size, argc);
whesse@chromium.orge90029b2010-08-02 11:52:17 +00001722}
1723
1724
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +00001725void MacroAssembler::LeaveExitFrame(int result_size) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001726 // Registers:
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001727 // r12 : argv
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001728
1729 // Get the return address from the stack and restore the frame pointer.
1730 movq(rcx, Operand(rbp, 1 * kPointerSize));
1731 movq(rbp, Operand(rbp, 0 * kPointerSize));
1732
ager@chromium.orga1645e22009-09-09 19:27:10 +00001733 // Pop everything up to and including the arguments and the receiver
1734 // from the caller stack.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001735 lea(rsp, Operand(r12, 1 * kPointerSize));
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001736
1737 // Restore current context from top and clear it in debug mode.
1738 ExternalReference context_address(Top::k_context_address);
1739 movq(kScratchRegister, context_address);
1740 movq(rsi, Operand(kScratchRegister, 0));
1741#ifdef DEBUG
1742 movq(Operand(kScratchRegister, 0), Immediate(0));
1743#endif
1744
1745 // Push the return address to get ready to return.
1746 push(rcx);
1747
1748 // Clear the top frame.
1749 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
1750 movq(kScratchRegister, c_entry_fp_address);
1751 movq(Operand(kScratchRegister, 0), Immediate(0));
1752}
1753
1754
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001755void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
1756 Register scratch,
1757 Label* miss) {
1758 Label same_contexts;
1759
1760 ASSERT(!holder_reg.is(scratch));
1761 ASSERT(!scratch.is(kScratchRegister));
1762 // Load current lexical context from the stack frame.
1763 movq(scratch, Operand(rbp, StandardFrameConstants::kContextOffset));
1764
1765 // When generating debug code, make sure the lexical context is set.
1766 if (FLAG_debug_code) {
1767 cmpq(scratch, Immediate(0));
1768 Check(not_equal, "we should not have an empty lexical context");
1769 }
1770 // Load the global context of the current context.
1771 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
1772 movq(scratch, FieldOperand(scratch, offset));
1773 movq(scratch, FieldOperand(scratch, GlobalObject::kGlobalContextOffset));
1774
1775 // Check the context is a global context.
1776 if (FLAG_debug_code) {
1777 Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
1778 Factory::global_context_map());
1779 Check(equal, "JSGlobalObject::global_context should be a global context.");
1780 }
1781
1782 // Check if both contexts are the same.
1783 cmpq(scratch, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
1784 j(equal, &same_contexts);
1785
1786 // Compare security tokens.
1787 // Check that the security token in the calling global object is
1788 // compatible with the security token in the receiving global
1789 // object.
1790
1791 // Check the context is a global context.
1792 if (FLAG_debug_code) {
1793 // Preserve original value of holder_reg.
1794 push(holder_reg);
1795 movq(holder_reg, FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001796 CompareRoot(holder_reg, Heap::kNullValueRootIndex);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001797 Check(not_equal, "JSGlobalProxy::context() should not be null.");
1798
1799 // Read the first word and compare to global_context_map(),
1800 movq(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001801 CompareRoot(holder_reg, Heap::kGlobalContextMapRootIndex);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001802 Check(equal, "JSGlobalObject::global_context should be a global context.");
1803 pop(holder_reg);
1804 }
1805
1806 movq(kScratchRegister,
1807 FieldOperand(holder_reg, JSGlobalProxy::kContextOffset));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001808 int token_offset =
1809 Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001810 movq(scratch, FieldOperand(scratch, token_offset));
1811 cmpq(scratch, FieldOperand(kScratchRegister, token_offset));
1812 j(not_equal, miss);
1813
1814 bind(&same_contexts);
1815}
1816
1817
ager@chromium.orga1645e22009-09-09 19:27:10 +00001818void MacroAssembler::LoadAllocationTopHelper(Register result,
1819 Register result_end,
1820 Register scratch,
1821 AllocationFlags flags) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001822 ExternalReference new_space_allocation_top =
1823 ExternalReference::new_space_allocation_top_address();
1824
1825 // Just return if allocation top is already known.
ager@chromium.orga1645e22009-09-09 19:27:10 +00001826 if ((flags & RESULT_CONTAINS_TOP) != 0) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001827 // No use of scratch if allocation top is provided.
ager@chromium.orgac091b72010-05-05 07:34:42 +00001828 ASSERT(!scratch.is_valid());
ager@chromium.orga1645e22009-09-09 19:27:10 +00001829#ifdef DEBUG
1830 // Assert that result actually contains top on entry.
1831 movq(kScratchRegister, new_space_allocation_top);
1832 cmpq(result, Operand(kScratchRegister, 0));
1833 Check(equal, "Unexpected allocation top");
1834#endif
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001835 return;
1836 }
1837
ager@chromium.orgac091b72010-05-05 07:34:42 +00001838 // Move address of new object to result. Use scratch register if available,
1839 // and keep address in scratch until call to UpdateAllocationTopHelper.
1840 if (scratch.is_valid()) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001841 ASSERT(!scratch.is(result_end));
1842 movq(scratch, new_space_allocation_top);
1843 movq(result, Operand(scratch, 0));
ager@chromium.orgac091b72010-05-05 07:34:42 +00001844 } else if (result.is(rax)) {
1845 load_rax(new_space_allocation_top);
1846 } else {
1847 movq(kScratchRegister, new_space_allocation_top);
1848 movq(result, Operand(kScratchRegister, 0));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001849 }
1850}
1851
1852
1853void MacroAssembler::UpdateAllocationTopHelper(Register result_end,
1854 Register scratch) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001855 if (FLAG_debug_code) {
1856 testq(result_end, Immediate(kObjectAlignmentMask));
1857 Check(zero, "Unaligned allocation in new space");
1858 }
1859
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001860 ExternalReference new_space_allocation_top =
1861 ExternalReference::new_space_allocation_top_address();
1862
1863 // Update new top.
1864 if (result_end.is(rax)) {
1865 // rax can be stored directly to a memory location.
1866 store_rax(new_space_allocation_top);
1867 } else {
1868 // Register required - use scratch provided if available.
ager@chromium.orgac091b72010-05-05 07:34:42 +00001869 if (scratch.is_valid()) {
1870 movq(Operand(scratch, 0), result_end);
1871 } else {
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001872 movq(kScratchRegister, new_space_allocation_top);
1873 movq(Operand(kScratchRegister, 0), result_end);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001874 }
1875 }
1876}
1877
1878
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001879void MacroAssembler::AllocateInNewSpace(int object_size,
1880 Register result,
1881 Register result_end,
1882 Register scratch,
1883 Label* gc_required,
1884 AllocationFlags flags) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001885 ASSERT(!result.is(result_end));
1886
1887 // Load address of new object into result.
ager@chromium.orga1645e22009-09-09 19:27:10 +00001888 LoadAllocationTopHelper(result, result_end, scratch, flags);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001889
1890 // Calculate new top and bail out if new space is exhausted.
1891 ExternalReference new_space_allocation_limit =
1892 ExternalReference::new_space_allocation_limit_address();
ager@chromium.orgac091b72010-05-05 07:34:42 +00001893
1894 Register top_reg = result_end.is_valid() ? result_end : result;
1895
1896 if (top_reg.is(result)) {
1897 addq(top_reg, Immediate(object_size));
1898 } else {
1899 lea(top_reg, Operand(result, object_size));
1900 }
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001901 movq(kScratchRegister, new_space_allocation_limit);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001902 cmpq(top_reg, Operand(kScratchRegister, 0));
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001903 j(above, gc_required);
1904
1905 // Update allocation top.
ager@chromium.orgac091b72010-05-05 07:34:42 +00001906 UpdateAllocationTopHelper(top_reg, scratch);
ager@chromium.orga1645e22009-09-09 19:27:10 +00001907
ager@chromium.orgac091b72010-05-05 07:34:42 +00001908 if (top_reg.is(result)) {
1909 if ((flags & TAG_OBJECT) != 0) {
1910 subq(result, Immediate(object_size - kHeapObjectTag));
1911 } else {
1912 subq(result, Immediate(object_size));
1913 }
1914 } else if ((flags & TAG_OBJECT) != 0) {
1915 // Tag the result if requested.
ager@chromium.orga1645e22009-09-09 19:27:10 +00001916 addq(result, Immediate(kHeapObjectTag));
1917 }
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001918}
1919
1920
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001921void MacroAssembler::AllocateInNewSpace(int header_size,
1922 ScaleFactor element_size,
1923 Register element_count,
1924 Register result,
1925 Register result_end,
1926 Register scratch,
1927 Label* gc_required,
1928 AllocationFlags flags) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001929 ASSERT(!result.is(result_end));
1930
1931 // Load address of new object into result.
ager@chromium.orga1645e22009-09-09 19:27:10 +00001932 LoadAllocationTopHelper(result, result_end, scratch, flags);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001933
1934 // Calculate new top and bail out if new space is exhausted.
1935 ExternalReference new_space_allocation_limit =
1936 ExternalReference::new_space_allocation_limit_address();
1937 lea(result_end, Operand(result, element_count, element_size, header_size));
1938 movq(kScratchRegister, new_space_allocation_limit);
1939 cmpq(result_end, Operand(kScratchRegister, 0));
1940 j(above, gc_required);
1941
1942 // Update allocation top.
1943 UpdateAllocationTopHelper(result_end, scratch);
ager@chromium.orga1645e22009-09-09 19:27:10 +00001944
1945 // Tag the result if requested.
1946 if ((flags & TAG_OBJECT) != 0) {
1947 addq(result, Immediate(kHeapObjectTag));
1948 }
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001949}
1950
1951
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001952void MacroAssembler::AllocateInNewSpace(Register object_size,
1953 Register result,
1954 Register result_end,
1955 Register scratch,
1956 Label* gc_required,
1957 AllocationFlags flags) {
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001958 // Load address of new object into result.
ager@chromium.orga1645e22009-09-09 19:27:10 +00001959 LoadAllocationTopHelper(result, result_end, scratch, flags);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001960
1961 // Calculate new top and bail out if new space is exhausted.
1962 ExternalReference new_space_allocation_limit =
1963 ExternalReference::new_space_allocation_limit_address();
1964 if (!object_size.is(result_end)) {
1965 movq(result_end, object_size);
1966 }
1967 addq(result_end, result);
1968 movq(kScratchRegister, new_space_allocation_limit);
1969 cmpq(result_end, Operand(kScratchRegister, 0));
1970 j(above, gc_required);
1971
1972 // Update allocation top.
1973 UpdateAllocationTopHelper(result_end, scratch);
ager@chromium.orga1645e22009-09-09 19:27:10 +00001974
1975 // Tag the result if requested.
1976 if ((flags & TAG_OBJECT) != 0) {
1977 addq(result, Immediate(kHeapObjectTag));
1978 }
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001979}
1980
1981
1982void MacroAssembler::UndoAllocationInNewSpace(Register object) {
1983 ExternalReference new_space_allocation_top =
1984 ExternalReference::new_space_allocation_top_address();
1985
1986 // Make sure the object has no tag before resetting top.
1987 and_(object, Immediate(~kHeapObjectTagMask));
1988 movq(kScratchRegister, new_space_allocation_top);
1989#ifdef DEBUG
1990 cmpq(object, Operand(kScratchRegister, 0));
1991 Check(below, "Undo allocation of non allocated memory");
1992#endif
1993 movq(Operand(kScratchRegister, 0), object);
1994}
1995
1996
ager@chromium.org3811b432009-10-28 14:53:37 +00001997void MacroAssembler::AllocateHeapNumber(Register result,
1998 Register scratch,
1999 Label* gc_required) {
2000 // Allocate heap number in new space.
2001 AllocateInNewSpace(HeapNumber::kSize,
2002 result,
2003 scratch,
2004 no_reg,
2005 gc_required,
2006 TAG_OBJECT);
2007
2008 // Set the map.
2009 LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
2010 movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
2011}
2012
2013
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00002014void MacroAssembler::AllocateTwoByteString(Register result,
2015 Register length,
2016 Register scratch1,
2017 Register scratch2,
2018 Register scratch3,
2019 Label* gc_required) {
2020 // Calculate the number of bytes needed for the characters in the string while
2021 // observing object alignment.
ager@chromium.orgac091b72010-05-05 07:34:42 +00002022 const int kHeaderAlignment = SeqTwoByteString::kHeaderSize &
2023 kObjectAlignmentMask;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00002024 ASSERT(kShortSize == 2);
2025 // scratch1 = length * 2 + kObjectAlignmentMask.
ager@chromium.orgac091b72010-05-05 07:34:42 +00002026 lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask +
2027 kHeaderAlignment));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00002028 and_(scratch1, Immediate(~kObjectAlignmentMask));
ager@chromium.orgac091b72010-05-05 07:34:42 +00002029 if (kHeaderAlignment > 0) {
2030 subq(scratch1, Immediate(kHeaderAlignment));
2031 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00002032
2033 // Allocate two byte string in new space.
2034 AllocateInNewSpace(SeqTwoByteString::kHeaderSize,
2035 times_1,
2036 scratch1,
2037 result,
2038 scratch2,
2039 scratch3,
2040 gc_required,
2041 TAG_OBJECT);
2042
2043 // Set the map, length and hash field.
2044 LoadRoot(kScratchRegister, Heap::kStringMapRootIndex);
2045 movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
ager@chromium.orgac091b72010-05-05 07:34:42 +00002046 Integer32ToSmi(scratch1, length);
2047 movq(FieldOperand(result, String::kLengthOffset), scratch1);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002048 movq(FieldOperand(result, String::kHashFieldOffset),
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00002049 Immediate(String::kEmptyHashField));
2050}
2051
2052
2053void MacroAssembler::AllocateAsciiString(Register result,
2054 Register length,
2055 Register scratch1,
2056 Register scratch2,
2057 Register scratch3,
2058 Label* gc_required) {
2059 // Calculate the number of bytes needed for the characters in the string while
2060 // observing object alignment.
ager@chromium.orgac091b72010-05-05 07:34:42 +00002061 const int kHeaderAlignment = SeqAsciiString::kHeaderSize &
2062 kObjectAlignmentMask;
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00002063 movl(scratch1, length);
2064 ASSERT(kCharSize == 1);
ager@chromium.orgac091b72010-05-05 07:34:42 +00002065 addq(scratch1, Immediate(kObjectAlignmentMask + kHeaderAlignment));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00002066 and_(scratch1, Immediate(~kObjectAlignmentMask));
ager@chromium.orgac091b72010-05-05 07:34:42 +00002067 if (kHeaderAlignment > 0) {
2068 subq(scratch1, Immediate(kHeaderAlignment));
2069 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00002070
2071 // Allocate ascii string in new space.
2072 AllocateInNewSpace(SeqAsciiString::kHeaderSize,
2073 times_1,
2074 scratch1,
2075 result,
2076 scratch2,
2077 scratch3,
2078 gc_required,
2079 TAG_OBJECT);
2080
2081 // Set the map, length and hash field.
2082 LoadRoot(kScratchRegister, Heap::kAsciiStringMapRootIndex);
2083 movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
ager@chromium.orgac091b72010-05-05 07:34:42 +00002084 Integer32ToSmi(scratch1, length);
2085 movq(FieldOperand(result, String::kLengthOffset), scratch1);
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002086 movq(FieldOperand(result, String::kHashFieldOffset),
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00002087 Immediate(String::kEmptyHashField));
2088}
2089
2090
2091void MacroAssembler::AllocateConsString(Register result,
2092 Register scratch1,
2093 Register scratch2,
2094 Label* gc_required) {
2095 // Allocate heap number in new space.
2096 AllocateInNewSpace(ConsString::kSize,
2097 result,
2098 scratch1,
2099 scratch2,
2100 gc_required,
2101 TAG_OBJECT);
2102
2103 // Set the map. The other fields are left uninitialized.
2104 LoadRoot(kScratchRegister, Heap::kConsStringMapRootIndex);
2105 movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
2106}
2107
2108
2109void MacroAssembler::AllocateAsciiConsString(Register result,
2110 Register scratch1,
2111 Register scratch2,
2112 Label* gc_required) {
2113 // Allocate heap number in new space.
2114 AllocateInNewSpace(ConsString::kSize,
2115 result,
2116 scratch1,
2117 scratch2,
2118 gc_required,
2119 TAG_OBJECT);
2120
2121 // Set the map. The other fields are left uninitialized.
2122 LoadRoot(kScratchRegister, Heap::kConsAsciiStringMapRootIndex);
2123 movq(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
2124}
2125
2126
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002127void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
2128 if (context_chain_length > 0) {
2129 // Move up the chain of contexts to the context containing the slot.
2130 movq(dst, Operand(rsi, Context::SlotOffset(Context::CLOSURE_INDEX)));
2131 // Load the function context (which is the incoming, outer context).
lrn@chromium.orgd5649e32010-01-19 13:36:12 +00002132 movq(dst, FieldOperand(dst, JSFunction::kContextOffset));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002133 for (int i = 1; i < context_chain_length; i++) {
2134 movq(dst, Operand(dst, Context::SlotOffset(Context::CLOSURE_INDEX)));
2135 movq(dst, FieldOperand(dst, JSFunction::kContextOffset));
2136 }
2137 // The context may be an intermediate context, not a function context.
2138 movq(dst, Operand(dst, Context::SlotOffset(Context::FCONTEXT_INDEX)));
2139 } else { // context is the current function context.
2140 // The context may be an intermediate context, not a function context.
2141 movq(dst, Operand(rsi, Context::SlotOffset(Context::FCONTEXT_INDEX)));
2142 }
2143}
2144
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002145
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002146int MacroAssembler::ArgumentStackSlotsForCFunctionCall(int num_arguments) {
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002147 // On Windows 64 stack slots are reserved by the caller for all arguments
2148 // including the ones passed in registers, and space is always allocated for
2149 // the four register arguments even if the function takes fewer than four
2150 // arguments.
2151 // On AMD64 ABI (Linux/Mac) the first six arguments are passed in registers
2152 // and the caller does not reserve stack slots for them.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002153 ASSERT(num_arguments >= 0);
2154#ifdef _WIN64
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002155 static const int kMinimumStackSlots = 4;
2156 if (num_arguments < kMinimumStackSlots) return kMinimumStackSlots;
2157 return num_arguments;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002158#else
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002159 static const int kRegisterPassedArguments = 6;
2160 if (num_arguments < kRegisterPassedArguments) return 0;
2161 return num_arguments - kRegisterPassedArguments;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002162#endif
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002163}
2164
ricow@chromium.org30ce4112010-05-31 10:38:25 +00002165
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002166void MacroAssembler::PrepareCallCFunction(int num_arguments) {
2167 int frame_alignment = OS::ActivationFrameAlignment();
2168 ASSERT(frame_alignment != 0);
2169 ASSERT(num_arguments >= 0);
2170 // Make stack end at alignment and allocate space for arguments and old rsp.
2171 movq(kScratchRegister, rsp);
2172 ASSERT(IsPowerOf2(frame_alignment));
2173 int argument_slots_on_stack =
2174 ArgumentStackSlotsForCFunctionCall(num_arguments);
2175 subq(rsp, Immediate((argument_slots_on_stack + 1) * kPointerSize));
2176 and_(rsp, Immediate(-frame_alignment));
2177 movq(Operand(rsp, argument_slots_on_stack * kPointerSize), kScratchRegister);
2178}
2179
2180
2181void MacroAssembler::CallCFunction(ExternalReference function,
2182 int num_arguments) {
2183 movq(rax, function);
2184 CallCFunction(rax, num_arguments);
2185}
2186
2187
2188void MacroAssembler::CallCFunction(Register function, int num_arguments) {
ricow@chromium.orgc9c80822010-04-21 08:22:37 +00002189 // Check stack alignment.
2190 if (FLAG_debug_code) {
2191 CheckStackAlignment();
2192 }
2193
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00002194 call(function);
2195 ASSERT(OS::ActivationFrameAlignment() != 0);
2196 ASSERT(num_arguments >= 0);
2197 int argument_slots_on_stack =
2198 ArgumentStackSlotsForCFunctionCall(num_arguments);
2199 movq(rsp, Operand(rsp, argument_slots_on_stack * kPointerSize));
2200}
2201
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00002202
ager@chromium.org4af710e2009-09-15 12:20:11 +00002203CodePatcher::CodePatcher(byte* address, int size)
2204 : address_(address), size_(size), masm_(address, size + Assembler::kGap) {
2205 // Create a new macro assembler pointing to the address of the code to patch.
2206 // The size is adjusted with kGap on order for the assembler to generate size
2207 // bytes of instructions without failing with buffer size constraints.
2208 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2209}
2210
2211
2212CodePatcher::~CodePatcher() {
2213 // Indicate that code has changed.
2214 CPU::FlushICache(address_, size_);
2215
2216 // Check that the code was patched as expected.
2217 ASSERT(masm_.pc_ == address_ + size_);
2218 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
2219}
2220
kasperl@chromium.org71affb52009-05-26 05:44:31 +00002221} } // namespace v8::internal
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00002222
2223#endif // V8_TARGET_ARCH_X64