Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/x64/macro-assembler-x64.cc

Issue 132373011: A64: Synchronize with r17635. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/macro-assembler-x64.h ('k') | src/x64/regexp-macro-assembler-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 73
74 Operand MacroAssembler::ExternalOperand(ExternalReference target, 74 Operand MacroAssembler::ExternalOperand(ExternalReference target,
75 Register scratch) { 75 Register scratch) {
76 if (root_array_available_ && !Serializer::enabled()) { 76 if (root_array_available_ && !Serializer::enabled()) {
77 intptr_t delta = RootRegisterDelta(target); 77 intptr_t delta = RootRegisterDelta(target);
78 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) { 78 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
79 Serializer::TooLateToEnableNow(); 79 Serializer::TooLateToEnableNow();
80 return Operand(kRootRegister, static_cast<int32_t>(delta)); 80 return Operand(kRootRegister, static_cast<int32_t>(delta));
81 } 81 }
82 } 82 }
83 movq(scratch, target); 83 Move(scratch, target);
84 return Operand(scratch, 0); 84 return Operand(scratch, 0);
85 } 85 }
86 86
87 87
88 void MacroAssembler::Load(Register destination, ExternalReference source) { 88 void MacroAssembler::Load(Register destination, ExternalReference source) {
89 if (root_array_available_ && !Serializer::enabled()) { 89 if (root_array_available_ && !Serializer::enabled()) {
90 intptr_t delta = RootRegisterDelta(source); 90 intptr_t delta = RootRegisterDelta(source);
91 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) { 91 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
92 Serializer::TooLateToEnableNow(); 92 Serializer::TooLateToEnableNow();
93 movq(destination, Operand(kRootRegister, static_cast<int32_t>(delta))); 93 movq(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
94 return; 94 return;
95 } 95 }
96 } 96 }
97 // Safe code. 97 // Safe code.
98 if (destination.is(rax)) { 98 if (destination.is(rax)) {
99 load_rax(source); 99 load_rax(source);
100 } else { 100 } else {
101 movq(kScratchRegister, source); 101 Move(kScratchRegister, source);
102 movq(destination, Operand(kScratchRegister, 0)); 102 movq(destination, Operand(kScratchRegister, 0));
103 } 103 }
104 } 104 }
105 105
106 106
107 void MacroAssembler::Store(ExternalReference destination, Register source) { 107 void MacroAssembler::Store(ExternalReference destination, Register source) {
108 if (root_array_available_ && !Serializer::enabled()) { 108 if (root_array_available_ && !Serializer::enabled()) {
109 intptr_t delta = RootRegisterDelta(destination); 109 intptr_t delta = RootRegisterDelta(destination);
110 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) { 110 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
111 Serializer::TooLateToEnableNow(); 111 Serializer::TooLateToEnableNow();
112 movq(Operand(kRootRegister, static_cast<int32_t>(delta)), source); 112 movq(Operand(kRootRegister, static_cast<int32_t>(delta)), source);
113 return; 113 return;
114 } 114 }
115 } 115 }
116 // Safe code. 116 // Safe code.
117 if (source.is(rax)) { 117 if (source.is(rax)) {
118 store_rax(destination); 118 store_rax(destination);
119 } else { 119 } else {
120 movq(kScratchRegister, destination); 120 Move(kScratchRegister, destination);
121 movq(Operand(kScratchRegister, 0), source); 121 movq(Operand(kScratchRegister, 0), source);
122 } 122 }
123 } 123 }
124 124
125 125
126 void MacroAssembler::LoadAddress(Register destination, 126 void MacroAssembler::LoadAddress(Register destination,
127 ExternalReference source) { 127 ExternalReference source) {
128 if (root_array_available_ && !Serializer::enabled()) { 128 if (root_array_available_ && !Serializer::enabled()) {
129 intptr_t delta = RootRegisterDelta(source); 129 intptr_t delta = RootRegisterDelta(source);
130 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) { 130 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
131 Serializer::TooLateToEnableNow(); 131 Serializer::TooLateToEnableNow();
132 lea(destination, Operand(kRootRegister, static_cast<int32_t>(delta))); 132 lea(destination, Operand(kRootRegister, static_cast<int32_t>(delta)));
133 return; 133 return;
134 } 134 }
135 } 135 }
136 // Safe code. 136 // Safe code.
137 movq(destination, source); 137 Move(destination, source);
138 } 138 }
139 139
140 140
141 int MacroAssembler::LoadAddressSize(ExternalReference source) { 141 int MacroAssembler::LoadAddressSize(ExternalReference source) {
142 if (root_array_available_ && !Serializer::enabled()) { 142 if (root_array_available_ && !Serializer::enabled()) {
143 // This calculation depends on the internals of LoadAddress. 143 // This calculation depends on the internals of LoadAddress.
144 // It's correctness is ensured by the asserts in the Call 144 // It's correctness is ensured by the asserts in the Call
145 // instruction below. 145 // instruction below.
146 intptr_t delta = RootRegisterDelta(source); 146 intptr_t delta = RootRegisterDelta(source);
147 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) { 147 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) {
148 Serializer::TooLateToEnableNow(); 148 Serializer::TooLateToEnableNow();
149 // Operand is lea(scratch, Operand(kRootRegister, delta)); 149 // Operand is lea(scratch, Operand(kRootRegister, delta));
150 // Opcodes : REX.W 8D ModRM Disp8/Disp32 - 4 or 7. 150 // Opcodes : REX.W 8D ModRM Disp8/Disp32 - 4 or 7.
151 int size = 4; 151 int size = 4;
152 if (!is_int8(static_cast<int32_t>(delta))) { 152 if (!is_int8(static_cast<int32_t>(delta))) {
153 size += 3; // Need full four-byte displacement in lea. 153 size += 3; // Need full four-byte displacement in lea.
154 } 154 }
155 return size; 155 return size;
156 } 156 }
157 } 157 }
158 // Size of movq(destination, src); 158 // Size of movq(destination, src);
159 return Assembler::kMoveAddressIntoScratchRegisterInstructionLength; 159 return Assembler::kMoveAddressIntoScratchRegisterInstructionLength;
160 } 160 }
161 161
162 162
163 void MacroAssembler::PushAddress(ExternalReference source) { 163 void MacroAssembler::PushAddress(ExternalReference source) {
164 int64_t address = reinterpret_cast<int64_t>(source.address()); 164 int64_t address = reinterpret_cast<int64_t>(source.address());
165 if (is_int32(address) && !Serializer::enabled()) { 165 if (is_int32(address) && !Serializer::enabled()) {
166 if (emit_debug_code()) { 166 if (emit_debug_code()) {
167 movq(kScratchRegister, BitCast<int64_t>(kZapValue), RelocInfo::NONE64); 167 movq(kScratchRegister, kZapValue, RelocInfo::NONE64);
168 } 168 }
169 push(Immediate(static_cast<int32_t>(address))); 169 push(Immediate(static_cast<int32_t>(address)));
170 return; 170 return;
171 } 171 }
172 LoadAddress(kScratchRegister, source); 172 LoadAddress(kScratchRegister, source);
173 push(kScratchRegister); 173 push(kScratchRegister);
174 } 174 }
175 175
176 176
177 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { 177 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 Register scratch, 269 Register scratch,
270 Condition cc, 270 Condition cc,
271 Label* branch, 271 Label* branch,
272 Label::Distance distance) { 272 Label::Distance distance) {
273 if (Serializer::enabled()) { 273 if (Serializer::enabled()) {
274 // Can't do arithmetic on external references if it might get serialized. 274 // Can't do arithmetic on external references if it might get serialized.
275 // The mask isn't really an address. We load it as an external reference in 275 // The mask isn't really an address. We load it as an external reference in
276 // case the size of the new space is different between the snapshot maker 276 // case the size of the new space is different between the snapshot maker
277 // and the running system. 277 // and the running system.
278 if (scratch.is(object)) { 278 if (scratch.is(object)) {
279 movq(kScratchRegister, ExternalReference::new_space_mask(isolate())); 279 Move(kScratchRegister, ExternalReference::new_space_mask(isolate()));
280 and_(scratch, kScratchRegister); 280 and_(scratch, kScratchRegister);
281 } else { 281 } else {
282 movq(scratch, ExternalReference::new_space_mask(isolate())); 282 Move(scratch, ExternalReference::new_space_mask(isolate()));
283 and_(scratch, object); 283 and_(scratch, object);
284 } 284 }
285 movq(kScratchRegister, ExternalReference::new_space_start(isolate())); 285 Move(kScratchRegister, ExternalReference::new_space_start(isolate()));
286 cmpq(scratch, kScratchRegister); 286 cmpq(scratch, kScratchRegister);
287 j(cc, branch, distance); 287 j(cc, branch, distance);
288 } else { 288 } else {
289 ASSERT(is_int32(static_cast<int64_t>(isolate()->heap()->NewSpaceMask()))); 289 ASSERT(is_int32(static_cast<int64_t>(isolate()->heap()->NewSpaceMask())));
290 intptr_t new_space_start = 290 intptr_t new_space_start =
291 reinterpret_cast<intptr_t>(isolate()->heap()->NewSpaceStart()); 291 reinterpret_cast<intptr_t>(isolate()->heap()->NewSpaceStart());
292 movq(kScratchRegister, -new_space_start, RelocInfo::NONE64); 292 movq(kScratchRegister, reinterpret_cast<Address>(-new_space_start),
293 RelocInfo::NONE64);
293 if (scratch.is(object)) { 294 if (scratch.is(object)) {
294 addq(scratch, kScratchRegister); 295 addq(scratch, kScratchRegister);
295 } else { 296 } else {
296 lea(scratch, Operand(object, kScratchRegister, times_1, 0)); 297 lea(scratch, Operand(object, kScratchRegister, times_1, 0));
297 } 298 }
298 and_(scratch, 299 and_(scratch,
299 Immediate(static_cast<int32_t>(isolate()->heap()->NewSpaceMask()))); 300 Immediate(static_cast<int32_t>(isolate()->heap()->NewSpaceMask())));
300 j(cc, branch, distance); 301 j(cc, branch, distance);
301 } 302 }
302 } 303 }
303 304
304 305
305 void MacroAssembler::RecordWriteField( 306 void MacroAssembler::RecordWriteField(
306 Register object, 307 Register object,
307 int offset, 308 int offset,
308 Register value, 309 Register value,
309 Register dst, 310 Register dst,
310 SaveFPRegsMode save_fp, 311 SaveFPRegsMode save_fp,
311 RememberedSetAction remembered_set_action, 312 RememberedSetAction remembered_set_action,
312 SmiCheck smi_check) { 313 SmiCheck smi_check) {
313 // The compiled code assumes that record write doesn't change the
314 // context register, so we check that none of the clobbered
315 // registers are rsi.
316 ASSERT(!value.is(rsi) && !dst.is(rsi));
317
318 // First, check if a write barrier is even needed. The tests below 314 // First, check if a write barrier is even needed. The tests below
319 // catch stores of Smis. 315 // catch stores of Smis.
320 Label done; 316 Label done;
321 317
322 // Skip barrier if writing a smi. 318 // Skip barrier if writing a smi.
323 if (smi_check == INLINE_SMI_CHECK) { 319 if (smi_check == INLINE_SMI_CHECK) {
324 JumpIfSmi(value, &done); 320 JumpIfSmi(value, &done);
325 } 321 }
326 322
327 // Although the object register is tagged, the offset is relative to the start 323 // Although the object register is tagged, the offset is relative to the start
(...skipping 10 matching lines...) Expand all
338 } 334 }
339 335
340 RecordWrite( 336 RecordWrite(
341 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); 337 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
342 338
343 bind(&done); 339 bind(&done);
344 340
345 // Clobber clobbered input registers when running with the debug-code flag 341 // Clobber clobbered input registers when running with the debug-code flag
346 // turned on to provoke errors. 342 // turned on to provoke errors.
347 if (emit_debug_code()) { 343 if (emit_debug_code()) {
348 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE64); 344 movq(value, kZapValue, RelocInfo::NONE64);
349 movq(dst, BitCast<int64_t>(kZapValue), RelocInfo::NONE64); 345 movq(dst, kZapValue, RelocInfo::NONE64);
350 } 346 }
351 } 347 }
352 348
353 349
354 void MacroAssembler::RecordWriteArray(Register object, 350 void MacroAssembler::RecordWriteArray(Register object,
355 Register value, 351 Register value,
356 Register index, 352 Register index,
357 SaveFPRegsMode save_fp, 353 SaveFPRegsMode save_fp,
358 RememberedSetAction remembered_set_action, 354 RememberedSetAction remembered_set_action,
359 SmiCheck smi_check) { 355 SmiCheck smi_check) {
(...skipping 12 matching lines...) Expand all
372 FixedArray::kHeaderSize - kHeapObjectTag)); 368 FixedArray::kHeaderSize - kHeapObjectTag));
373 369
374 RecordWrite( 370 RecordWrite(
375 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); 371 object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
376 372
377 bind(&done); 373 bind(&done);
378 374
379 // Clobber clobbered input registers when running with the debug-code flag 375 // Clobber clobbered input registers when running with the debug-code flag
380 // turned on to provoke errors. 376 // turned on to provoke errors.
381 if (emit_debug_code()) { 377 if (emit_debug_code()) {
382 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE64); 378 movq(value, kZapValue, RelocInfo::NONE64);
383 movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE64); 379 movq(index, kZapValue, RelocInfo::NONE64);
384 } 380 }
385 } 381 }
386 382
387 383
388 void MacroAssembler::RecordWrite(Register object, 384 void MacroAssembler::RecordWrite(Register object,
389 Register address, 385 Register address,
390 Register value, 386 Register value,
391 SaveFPRegsMode fp_mode, 387 SaveFPRegsMode fp_mode,
392 RememberedSetAction remembered_set_action, 388 RememberedSetAction remembered_set_action,
393 SmiCheck smi_check) { 389 SmiCheck smi_check) {
394 // The compiled code assumes that record write doesn't change the
395 // context register, so we check that none of the clobbered
396 // registers are rsi.
397 ASSERT(!value.is(rsi) && !address.is(rsi));
398
399 ASSERT(!object.is(value)); 390 ASSERT(!object.is(value));
400 ASSERT(!object.is(address)); 391 ASSERT(!object.is(address));
401 ASSERT(!value.is(address)); 392 ASSERT(!value.is(address));
402 AssertNotSmi(object); 393 AssertNotSmi(object);
403 394
404 if (remembered_set_action == OMIT_REMEMBERED_SET && 395 if (remembered_set_action == OMIT_REMEMBERED_SET &&
405 !FLAG_incremental_marking) { 396 !FLAG_incremental_marking) {
406 return; 397 return;
407 } 398 }
408 399
(...skipping 29 matching lines...) Expand all
438 Label::kNear); 429 Label::kNear);
439 430
440 RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode); 431 RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode);
441 CallStub(&stub); 432 CallStub(&stub);
442 433
443 bind(&done); 434 bind(&done);
444 435
445 // Clobber clobbered registers when running with the debug-code flag 436 // Clobber clobbered registers when running with the debug-code flag
446 // turned on to provoke errors. 437 // turned on to provoke errors.
447 if (emit_debug_code()) { 438 if (emit_debug_code()) {
448 movq(address, BitCast<int64_t>(kZapValue), RelocInfo::NONE64); 439 movq(address, kZapValue, RelocInfo::NONE64);
449 movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE64); 440 movq(value, kZapValue, RelocInfo::NONE64);
450 } 441 }
451 } 442 }
452 443
453 444
454 void MacroAssembler::Assert(Condition cc, BailoutReason reason) { 445 void MacroAssembler::Assert(Condition cc, BailoutReason reason) {
455 if (emit_debug_code()) Check(cc, reason); 446 if (emit_debug_code()) Check(cc, reason);
456 } 447 }
457 448
458 449
459 void MacroAssembler::AssertFastElements(Register elements) { 450 void MacroAssembler::AssertFastElements(Register elements) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 RecordComment(msg); 518 RecordComment(msg);
528 } 519 }
529 520
530 if (FLAG_trap_on_abort) { 521 if (FLAG_trap_on_abort) {
531 int3(); 522 int3();
532 return; 523 return;
533 } 524 }
534 #endif 525 #endif
535 526
536 push(rax); 527 push(rax);
537 movq(kScratchRegister, p0, RelocInfo::NONE64); 528 movq(kScratchRegister, reinterpret_cast<Smi*>(p0), RelocInfo::NONE64);
538 push(kScratchRegister); 529 push(kScratchRegister);
539 movq(kScratchRegister, 530 movq(kScratchRegister, Smi::FromInt(static_cast<int>(p1 - p0)),
540 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(p1 - p0))),
541 RelocInfo::NONE64); 531 RelocInfo::NONE64);
542 push(kScratchRegister); 532 push(kScratchRegister);
543 533
544 if (!has_frame_) { 534 if (!has_frame_) {
545 // We don't actually want to generate a pile of code for this, so just 535 // We don't actually want to generate a pile of code for this, so just
546 // claim there is a stack frame, without generating one. 536 // claim there is a stack frame, without generating one.
547 FrameScope scope(this, StackFrame::NONE); 537 FrameScope scope(this, StackFrame::NONE);
548 CallRuntime(Runtime::kAbort, 2); 538 CallRuntime(Runtime::kAbort, 2);
549 } else { 539 } else {
550 CallRuntime(Runtime::kAbort, 2); 540 CallRuntime(Runtime::kAbort, 2);
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 const int kLevelOffset = Offset( 693 const int kLevelOffset = Offset(
704 ExternalReference::handle_scope_level_address(isolate()), 694 ExternalReference::handle_scope_level_address(isolate()),
705 next_address); 695 next_address);
706 ExternalReference scheduled_exception_address = 696 ExternalReference scheduled_exception_address =
707 ExternalReference::scheduled_exception_address(isolate()); 697 ExternalReference::scheduled_exception_address(isolate());
708 698
709 // Allocate HandleScope in callee-save registers. 699 // Allocate HandleScope in callee-save registers.
710 Register prev_next_address_reg = r14; 700 Register prev_next_address_reg = r14;
711 Register prev_limit_reg = rbx; 701 Register prev_limit_reg = rbx;
712 Register base_reg = r15; 702 Register base_reg = r15;
713 movq(base_reg, next_address); 703 Move(base_reg, next_address);
714 movq(prev_next_address_reg, Operand(base_reg, kNextOffset)); 704 movq(prev_next_address_reg, Operand(base_reg, kNextOffset));
715 movq(prev_limit_reg, Operand(base_reg, kLimitOffset)); 705 movq(prev_limit_reg, Operand(base_reg, kLimitOffset));
716 addl(Operand(base_reg, kLevelOffset), Immediate(1)); 706 addl(Operand(base_reg, kLevelOffset), Immediate(1));
717 707
718 if (FLAG_log_timer_events) { 708 if (FLAG_log_timer_events) {
719 FrameScope frame(this, StackFrame::MANUAL); 709 FrameScope frame(this, StackFrame::MANUAL);
720 PushSafepointRegisters(); 710 PushSafepointRegisters();
721 PrepareCallCFunction(1); 711 PrepareCallCFunction(1);
722 LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate())); 712 LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate()));
723 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1); 713 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 754
765 // No more valid handles (the result handle was the last one). Restore 755 // No more valid handles (the result handle was the last one). Restore
766 // previous handle scope. 756 // previous handle scope.
767 subl(Operand(base_reg, kLevelOffset), Immediate(1)); 757 subl(Operand(base_reg, kLevelOffset), Immediate(1));
768 movq(Operand(base_reg, kNextOffset), prev_next_address_reg); 758 movq(Operand(base_reg, kNextOffset), prev_next_address_reg);
769 cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset)); 759 cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset));
770 j(not_equal, &delete_allocated_handles); 760 j(not_equal, &delete_allocated_handles);
771 bind(&leave_exit_frame); 761 bind(&leave_exit_frame);
772 762
773 // Check if the function scheduled an exception. 763 // Check if the function scheduled an exception.
774 movq(rsi, scheduled_exception_address); 764 Move(rsi, scheduled_exception_address);
775 Cmp(Operand(rsi, 0), factory->the_hole_value()); 765 Cmp(Operand(rsi, 0), factory->the_hole_value());
776 j(not_equal, &promote_scheduled_exception); 766 j(not_equal, &promote_scheduled_exception);
777 bind(&exception_handled); 767 bind(&exception_handled);
778 768
779 #if ENABLE_EXTRA_CHECKS 769 #if ENABLE_EXTRA_CHECKS
780 // Check if the function returned a valid JavaScript value. 770 // Check if the function returned a valid JavaScript value.
781 Label ok; 771 Label ok;
782 Register return_value = rax; 772 Register return_value = rax;
783 Register map = rcx; 773 Register map = rcx;
784 774
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 933
944 934
945 void MacroAssembler::Cvtlsi2sd(XMMRegister dst, const Operand& src) { 935 void MacroAssembler::Cvtlsi2sd(XMMRegister dst, const Operand& src) {
946 xorps(dst, dst); 936 xorps(dst, dst);
947 cvtlsi2sd(dst, src); 937 cvtlsi2sd(dst, src);
948 } 938 }
949 939
950 940
951 void MacroAssembler::Load(Register dst, const Operand& src, Representation r) { 941 void MacroAssembler::Load(Register dst, const Operand& src, Representation r) {
952 ASSERT(!r.IsDouble()); 942 ASSERT(!r.IsDouble());
953 if (r.IsByte()) { 943 if (r.IsInteger8()) {
944 movsxbq(dst, src);
945 } else if (r.IsUInteger8()) {
954 movzxbl(dst, src); 946 movzxbl(dst, src);
947 } else if (r.IsInteger16()) {
948 movsxwq(dst, src);
949 } else if (r.IsUInteger16()) {
950 movzxwl(dst, src);
955 } else if (r.IsInteger32()) { 951 } else if (r.IsInteger32()) {
956 movl(dst, src); 952 movl(dst, src);
957 } else { 953 } else {
958 movq(dst, src); 954 movq(dst, src);
959 } 955 }
960 } 956 }
961 957
962 958
963 void MacroAssembler::Store(const Operand& dst, Register src, Representation r) { 959 void MacroAssembler::Store(const Operand& dst, Register src, Representation r) {
964 ASSERT(!r.IsDouble()); 960 ASSERT(!r.IsDouble());
965 if (r.IsByte()) { 961 if (r.IsInteger8() || r.IsUInteger8()) {
966 movb(dst, src); 962 movb(dst, src);
963 } else if (r.IsInteger16() || r.IsUInteger16()) {
964 movw(dst, src);
967 } else if (r.IsInteger32()) { 965 } else if (r.IsInteger32()) {
968 movl(dst, src); 966 movl(dst, src);
969 } else { 967 } else {
970 movq(dst, src); 968 movq(dst, src);
971 } 969 }
972 } 970 }
973 971
974 972
975 void MacroAssembler::Set(Register dst, int64_t x) { 973 void MacroAssembler::Set(Register dst, int64_t x) {
976 if (x == 0) { 974 if (x == 0) {
977 xorl(dst, dst); 975 xorl(dst, dst);
978 } else if (is_uint32(x)) { 976 } else if (is_uint32(x)) {
979 movl(dst, Immediate(static_cast<uint32_t>(x))); 977 movl(dst, Immediate(static_cast<uint32_t>(x)));
980 } else if (is_int32(x)) { 978 } else if (is_int32(x)) {
981 movq(dst, Immediate(static_cast<int32_t>(x))); 979 movq(dst, Immediate(static_cast<int32_t>(x)));
982 } else { 980 } else {
983 movq(dst, x, RelocInfo::NONE64); 981 movq(dst, x);
984 } 982 }
985 } 983 }
986 984
987 985
988 void MacroAssembler::Set(const Operand& dst, int64_t x) { 986 void MacroAssembler::Set(const Operand& dst, int64_t x) {
989 if (is_int32(x)) { 987 if (is_int32(x)) {
990 movq(dst, Immediate(static_cast<int32_t>(x))); 988 movq(dst, Immediate(static_cast<int32_t>(x)));
991 } else { 989 } else {
992 Set(kScratchRegister, x); 990 Set(kScratchRegister, x);
993 movq(dst, kScratchRegister); 991 movq(dst, kScratchRegister);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1038 if (value == 1) { 1036 if (value == 1) {
1039 return kSmiConstantRegister; 1037 return kSmiConstantRegister;
1040 } 1038 }
1041 LoadSmiConstant(kScratchRegister, source); 1039 LoadSmiConstant(kScratchRegister, source);
1042 return kScratchRegister; 1040 return kScratchRegister;
1043 } 1041 }
1044 1042
1045 1043
1046 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) { 1044 void MacroAssembler::LoadSmiConstant(Register dst, Smi* source) {
1047 if (emit_debug_code()) { 1045 if (emit_debug_code()) {
1048 movq(dst, 1046 movq(dst, Smi::FromInt(kSmiConstantRegisterValue), RelocInfo::NONE64);
1049 reinterpret_cast<uint64_t>(Smi::FromInt(kSmiConstantRegisterValue)),
1050 RelocInfo::NONE64);
1051 cmpq(dst, kSmiConstantRegister); 1047 cmpq(dst, kSmiConstantRegister);
1052 if (allow_stub_calls()) { 1048 if (allow_stub_calls()) {
1053 Assert(equal, kUninitializedKSmiConstantRegister); 1049 Assert(equal, kUninitializedKSmiConstantRegister);
1054 } else { 1050 } else {
1055 Label ok; 1051 Label ok;
1056 j(equal, &ok, Label::kNear); 1052 j(equal, &ok, Label::kNear);
1057 int3(); 1053 int3();
1058 bind(&ok); 1054 bind(&ok);
1059 } 1055 }
1060 } 1056 }
(...skipping 26 matching lines...) Expand all
1087 case 2: 1083 case 2:
1088 lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0)); 1084 lea(dst, Operand(kSmiConstantRegister, kSmiConstantRegister, times_1, 0));
1089 break; 1085 break;
1090 case 1: 1086 case 1:
1091 movq(dst, kSmiConstantRegister); 1087 movq(dst, kSmiConstantRegister);
1092 break; 1088 break;
1093 case 0: 1089 case 0:
1094 UNREACHABLE(); 1090 UNREACHABLE();
1095 return; 1091 return;
1096 default: 1092 default:
1097 movq(dst, reinterpret_cast<uint64_t>(source), RelocInfo::NONE64); 1093 movq(dst, source, RelocInfo::NONE64);
1098 return; 1094 return;
1099 } 1095 }
1100 if (negative) { 1096 if (negative) {
1101 neg(dst); 1097 neg(dst);
1102 } 1098 }
1103 } 1099 }
1104 1100
1105 1101
1106 void MacroAssembler::Integer32ToSmi(Register dst, Register src) { 1102 void MacroAssembler::Integer32ToSmi(Register dst, Register src) {
1107 STATIC_ASSERT(kSmiTag == 0); 1103 STATIC_ASSERT(kSmiTag == 0);
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
1511 void MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) { 1507 void MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
1512 if (constant->value() != 0) { 1508 if (constant->value() != 0) {
1513 addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value())); 1509 addl(Operand(dst, kSmiShift / kBitsPerByte), Immediate(constant->value()));
1514 } 1510 }
1515 } 1511 }
1516 1512
1517 1513
1518 void MacroAssembler::SmiAddConstant(Register dst, 1514 void MacroAssembler::SmiAddConstant(Register dst,
1519 Register src, 1515 Register src,
1520 Smi* constant, 1516 Smi* constant,
1521 Label* on_not_smi_result, 1517 SmiOperationExecutionMode mode,
1518 Label* bailout_label,
1522 Label::Distance near_jump) { 1519 Label::Distance near_jump) {
1523 if (constant->value() == 0) { 1520 if (constant->value() == 0) {
1524 if (!dst.is(src)) { 1521 if (!dst.is(src)) {
1525 movq(dst, src); 1522 movq(dst, src);
1526 } 1523 }
1527 } else if (dst.is(src)) { 1524 } else if (dst.is(src)) {
1528 ASSERT(!dst.is(kScratchRegister)); 1525 ASSERT(!dst.is(kScratchRegister));
1529
1530 Label done;
1531 LoadSmiConstant(kScratchRegister, constant); 1526 LoadSmiConstant(kScratchRegister, constant);
1532 addq(dst, kScratchRegister); 1527 addq(dst, kScratchRegister);
1533 j(no_overflow, &done, Label::kNear); 1528 if (mode.Contains(BAILOUT_ON_NO_OVERFLOW)) {
1534 // Restore src. 1529 j(no_overflow, bailout_label, near_jump);
1535 subq(dst, kScratchRegister); 1530 ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER));
1536 jmp(on_not_smi_result, near_jump); 1531 subq(dst, kScratchRegister);
1537 bind(&done); 1532 } else if (mode.Contains(BAILOUT_ON_OVERFLOW)) {
1533 if (mode.Contains(PRESERVE_SOURCE_REGISTER)) {
1534 Label done;
1535 j(no_overflow, &done, Label::kNear);
1536 subq(dst, kScratchRegister);
1537 jmp(bailout_label, near_jump);
1538 bind(&done);
1539 } else {
1540 // Bailout if overflow without reserving src.
1541 j(overflow, bailout_label, near_jump);
1542 }
1543 } else {
1544 CHECK(mode.IsEmpty());
1545 }
1538 } else { 1546 } else {
1547 ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER));
1548 ASSERT(mode.Contains(BAILOUT_ON_OVERFLOW));
1539 LoadSmiConstant(dst, constant); 1549 LoadSmiConstant(dst, constant);
1540 addq(dst, src); 1550 addq(dst, src);
1541 j(overflow, on_not_smi_result, near_jump); 1551 j(overflow, bailout_label, near_jump);
1542 } 1552 }
1543 } 1553 }
1544 1554
1545 1555
1546 void MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) { 1556 void MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant) {
1547 if (constant->value() == 0) { 1557 if (constant->value() == 0) {
1548 if (!dst.is(src)) { 1558 if (!dst.is(src)) {
1549 movq(dst, src); 1559 movq(dst, src);
1550 } 1560 }
1551 } else if (dst.is(src)) { 1561 } else if (dst.is(src)) {
(...skipping 11 matching lines...) Expand all
1563 LoadSmiConstant(dst, Smi::FromInt(-constant->value())); 1573 LoadSmiConstant(dst, Smi::FromInt(-constant->value()));
1564 addq(dst, src); 1574 addq(dst, src);
1565 } 1575 }
1566 } 1576 }
1567 } 1577 }
1568 1578
1569 1579
1570 void MacroAssembler::SmiSubConstant(Register dst, 1580 void MacroAssembler::SmiSubConstant(Register dst,
1571 Register src, 1581 Register src,
1572 Smi* constant, 1582 Smi* constant,
1573 Label* on_not_smi_result, 1583 SmiOperationExecutionMode mode,
1584 Label* bailout_label,
1574 Label::Distance near_jump) { 1585 Label::Distance near_jump) {
1575 if (constant->value() == 0) { 1586 if (constant->value() == 0) {
1576 if (!dst.is(src)) { 1587 if (!dst.is(src)) {
1577 movq(dst, src); 1588 movq(dst, src);
1578 } 1589 }
1579 } else if (dst.is(src)) { 1590 } else if (dst.is(src)) {
1580 ASSERT(!dst.is(kScratchRegister)); 1591 ASSERT(!dst.is(kScratchRegister));
1592 LoadSmiConstant(kScratchRegister, constant);
1593 subq(dst, kScratchRegister);
1594 if (mode.Contains(BAILOUT_ON_NO_OVERFLOW)) {
1595 j(no_overflow, bailout_label, near_jump);
1596 ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER));
1597 addq(dst, kScratchRegister);
1598 } else if (mode.Contains(BAILOUT_ON_OVERFLOW)) {
1599 if (mode.Contains(PRESERVE_SOURCE_REGISTER)) {
1600 Label done;
1601 j(no_overflow, &done, Label::kNear);
1602 addq(dst, kScratchRegister);
1603 jmp(bailout_label, near_jump);
1604 bind(&done);
1605 } else {
1606 // Bailout if overflow without reserving src.
1607 j(overflow, bailout_label, near_jump);
1608 }
1609 } else {
1610 CHECK(mode.IsEmpty());
1611 }
1612 } else {
1613 ASSERT(mode.Contains(PRESERVE_SOURCE_REGISTER));
1614 ASSERT(mode.Contains(BAILOUT_ON_OVERFLOW));
1581 if (constant->value() == Smi::kMinValue) { 1615 if (constant->value() == Smi::kMinValue) {
1582 // Subtracting min-value from any non-negative value will overflow. 1616 ASSERT(!dst.is(kScratchRegister));
1583 // We test the non-negativeness before doing the subtraction. 1617 movq(dst, src);
1584 testq(src, src);
1585 j(not_sign, on_not_smi_result, near_jump);
1586 LoadSmiConstant(kScratchRegister, constant); 1618 LoadSmiConstant(kScratchRegister, constant);
1587 subq(dst, kScratchRegister); 1619 subq(dst, kScratchRegister);
1588 } else { 1620 j(overflow, bailout_label, near_jump);
1589 // Subtract by adding the negation.
1590 LoadSmiConstant(kScratchRegister, Smi::FromInt(-constant->value()));
1591 addq(kScratchRegister, dst);
1592 j(overflow, on_not_smi_result, near_jump);
1593 movq(dst, kScratchRegister);
1594 }
1595 } else {
1596 if (constant->value() == Smi::kMinValue) {
1597 // Subtracting min-value from any non-negative value will overflow.
1598 // We test the non-negativeness before doing the subtraction.
1599 testq(src, src);
1600 j(not_sign, on_not_smi_result, near_jump);
1601 LoadSmiConstant(dst, constant);
1602 // Adding and subtracting the min-value gives the same result, it only
1603 // differs on the overflow bit, which we don't check here.
1604 addq(dst, src);
1605 } else { 1621 } else {
1606 // Subtract by adding the negation. 1622 // Subtract by adding the negation.
1607 LoadSmiConstant(dst, Smi::FromInt(-(constant->value()))); 1623 LoadSmiConstant(dst, Smi::FromInt(-(constant->value())));
1608 addq(dst, src); 1624 addq(dst, src);
1609 j(overflow, on_not_smi_result, near_jump); 1625 j(overflow, bailout_label, near_jump);
1610 } 1626 }
1611 } 1627 }
1612 } 1628 }
1613 1629
1614 1630
1615 void MacroAssembler::SmiNeg(Register dst, 1631 void MacroAssembler::SmiNeg(Register dst,
1616 Register src, 1632 Register src,
1617 Label* on_smi_result, 1633 Label* on_smi_result,
1618 Label::Distance near_jump) { 1634 Label::Distance near_jump) {
1619 if (dst.is(src)) { 1635 if (dst.is(src)) {
(...skipping 1390 matching lines...) Expand 10 before | Expand all | Expand 10 after
3010 // Preserve original value. 3026 // Preserve original value.
3011 SmiToInteger32(kScratchRegister, maybe_number); 3027 SmiToInteger32(kScratchRegister, maybe_number);
3012 Cvtlsi2sd(xmm_scratch, kScratchRegister); 3028 Cvtlsi2sd(xmm_scratch, kScratchRegister);
3013 movsd(FieldOperand(elements, index, times_8, 3029 movsd(FieldOperand(elements, index, times_8,
3014 FixedDoubleArray::kHeaderSize - elements_offset), 3030 FixedDoubleArray::kHeaderSize - elements_offset),
3015 xmm_scratch); 3031 xmm_scratch);
3016 bind(&done); 3032 bind(&done);
3017 } 3033 }
3018 3034
3019 3035
3020 void MacroAssembler::CompareMap(Register obj, 3036 void MacroAssembler::CompareMap(Register obj, Handle<Map> map) {
3021 Handle<Map> map,
3022 Label* early_success) {
3023 Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); 3037 Cmp(FieldOperand(obj, HeapObject::kMapOffset), map);
3024 } 3038 }
3025 3039
3026 3040
3027 void MacroAssembler::CheckMap(Register obj, 3041 void MacroAssembler::CheckMap(Register obj,
3028 Handle<Map> map, 3042 Handle<Map> map,
3029 Label* fail, 3043 Label* fail,
3030 SmiCheckType smi_check_type) { 3044 SmiCheckType smi_check_type) {
3031 if (smi_check_type == DO_SMI_CHECK) { 3045 if (smi_check_type == DO_SMI_CHECK) {
3032 JumpIfSmi(obj, fail); 3046 JumpIfSmi(obj, fail);
3033 } 3047 }
3034 3048
3035 Label success; 3049 CompareMap(obj, map);
3036 CompareMap(obj, map, &success);
3037 j(not_equal, fail); 3050 j(not_equal, fail);
3038 bind(&success);
3039 } 3051 }
3040 3052
3041 3053
3042 void MacroAssembler::ClampUint8(Register reg) { 3054 void MacroAssembler::ClampUint8(Register reg) {
3043 Label done; 3055 Label done;
3044 testl(reg, Immediate(0xFFFFFF00)); 3056 testl(reg, Immediate(0xFFFFFF00));
3045 j(zero, &done, Label::kNear); 3057 j(zero, &done, Label::kNear);
3046 setcc(negative, reg); // 1 if negative, 0 if positive. 3058 setcc(negative, reg); // 1 if negative, 0 if positive.
3047 decb(reg); // 0 if negative, 255 if positive. 3059 decb(reg); // 0 if negative, 255 if positive.
3048 bind(&done); 3060 bind(&done);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
3113 } 3125 }
3114 3126
3115 bind(&done); 3127 bind(&done);
3116 } 3128 }
3117 3129
3118 3130
3119 void MacroAssembler::TruncateDoubleToI(Register result_reg, 3131 void MacroAssembler::TruncateDoubleToI(Register result_reg,
3120 XMMRegister input_reg) { 3132 XMMRegister input_reg) {
3121 Label done; 3133 Label done;
3122 cvttsd2siq(result_reg, input_reg); 3134 cvttsd2siq(result_reg, input_reg);
3123 movq(kScratchRegister, 3135 movq(kScratchRegister, V8_INT64_C(0x8000000000000000));
3124 V8_INT64_C(0x8000000000000000),
3125 RelocInfo::NONE64);
3126 cmpq(result_reg, kScratchRegister); 3136 cmpq(result_reg, kScratchRegister);
3127 j(not_equal, &done, Label::kNear); 3137 j(not_equal, &done, Label::kNear);
3128 3138
3129 subq(rsp, Immediate(kDoubleSize)); 3139 subq(rsp, Immediate(kDoubleSize));
3130 movsd(MemOperand(rsp, 0), input_reg); 3140 movsd(MemOperand(rsp, 0), input_reg);
3131 SlowTruncateToI(result_reg, rsp, 0); 3141 SlowTruncateToI(result_reg, rsp, 0);
3132 addq(rsp, Immediate(kDoubleSize)); 3142 addq(rsp, Immediate(kDoubleSize));
3133 3143
3134 bind(&done); 3144 bind(&done);
3135 } 3145 }
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
3265 if (emit_debug_code()) { 3275 if (emit_debug_code()) {
3266 Condition is_smi = CheckSmi(object); 3276 Condition is_smi = CheckSmi(object);
3267 Check(is_smi, kOperandIsNotASmi); 3277 Check(is_smi, kOperandIsNotASmi);
3268 } 3278 }
3269 } 3279 }
3270 3280
3271 3281
3272 void MacroAssembler::AssertZeroExtended(Register int32_register) { 3282 void MacroAssembler::AssertZeroExtended(Register int32_register) {
3273 if (emit_debug_code()) { 3283 if (emit_debug_code()) {
3274 ASSERT(!int32_register.is(kScratchRegister)); 3284 ASSERT(!int32_register.is(kScratchRegister));
3275 movq(kScratchRegister, 0x100000000l, RelocInfo::NONE64); 3285 movq(kScratchRegister, V8_INT64_C(0x0000000100000000));
3276 cmpq(kScratchRegister, int32_register); 3286 cmpq(kScratchRegister, int32_register);
3277 Check(above_equal, k32BitValueInRegisterIsNotZeroExtended); 3287 Check(above_equal, k32BitValueInRegisterIsNotZeroExtended);
3278 } 3288 }
3279 } 3289 }
3280 3290
3281 3291
3282 void MacroAssembler::AssertString(Register object) { 3292 void MacroAssembler::AssertString(Register object) {
3283 if (emit_debug_code()) { 3293 if (emit_debug_code()) {
3284 testb(object, Immediate(kSmiTagMask)); 3294 testb(object, Immediate(kSmiTagMask));
3285 Check(not_equal, kOperandIsASmiAndNotAString); 3295 Check(not_equal, kOperandIsASmiAndNotAString);
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after
4064 4074
4065 4075
4066 void MacroAssembler::Allocate(int object_size, 4076 void MacroAssembler::Allocate(int object_size,
4067 Register result, 4077 Register result,
4068 Register result_end, 4078 Register result_end,
4069 Register scratch, 4079 Register scratch,
4070 Label* gc_required, 4080 Label* gc_required,
4071 AllocationFlags flags) { 4081 AllocationFlags flags) {
4072 ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0); 4082 ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0);
4073 ASSERT(object_size <= Page::kMaxNonCodeHeapObjectSize); 4083 ASSERT(object_size <= Page::kMaxNonCodeHeapObjectSize);
4074 if (!FLAG_inline_new) { 4084 if (!FLAG_inline_new ||
4085 // TODO(mstarzinger): Implement more efficiently by keeping then
4086 // bump-pointer allocation area empty instead of recompiling code.
4087 isolate()->heap_profiler()->is_tracking_allocations()) {
4075 if (emit_debug_code()) { 4088 if (emit_debug_code()) {
4076 // Trash the registers to simulate an allocation failure. 4089 // Trash the registers to simulate an allocation failure.
4077 movl(result, Immediate(0x7091)); 4090 movl(result, Immediate(0x7091));
4078 if (result_end.is_valid()) { 4091 if (result_end.is_valid()) {
4079 movl(result_end, Immediate(0x7191)); 4092 movl(result_end, Immediate(0x7191));
4080 } 4093 }
4081 if (scratch.is_valid()) { 4094 if (scratch.is_valid()) {
4082 movl(scratch, Immediate(0x7291)); 4095 movl(scratch, Immediate(0x7291));
4083 } 4096 }
4084 } 4097 }
4085 jmp(gc_required); 4098 jmp(gc_required);
4086 return; 4099 return;
4087 } 4100 }
4088 ASSERT(!result.is(result_end)); 4101 ASSERT(!result.is(result_end));
4089 4102
4090 // Load address of new object into result. 4103 // Load address of new object into result.
4091 LoadAllocationTopHelper(result, scratch, flags); 4104 LoadAllocationTopHelper(result, scratch, flags);
4092 4105
4093 if (isolate()->heap_profiler()->is_tracking_allocations()) {
4094 RecordObjectAllocation(isolate(), result, object_size);
4095 }
4096
4097 // Align the next allocation. Storing the filler map without checking top is 4106 // Align the next allocation. Storing the filler map without checking top is
4098 // safe in new-space because the limit of the heap is aligned there. 4107 // safe in new-space because the limit of the heap is aligned there.
4099 if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) { 4108 if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) {
4100 testq(result, Immediate(kDoubleAlignmentMask)); 4109 testq(result, Immediate(kDoubleAlignmentMask));
4101 Check(zero, kAllocationIsNotDoubleAligned); 4110 Check(zero, kAllocationIsNotDoubleAligned);
4102 } 4111 }
4103 4112
4104 // Calculate new top and bail out if new space is exhausted. 4113 // Calculate new top and bail out if new space is exhausted.
4105 ExternalReference allocation_limit = 4114 ExternalReference allocation_limit =
4106 AllocationUtils::GetAllocationLimitReference(isolate(), flags); 4115 AllocationUtils::GetAllocationLimitReference(isolate(), flags);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
4148 } 4157 }
4149 4158
4150 4159
4151 void MacroAssembler::Allocate(Register object_size, 4160 void MacroAssembler::Allocate(Register object_size,
4152 Register result, 4161 Register result,
4153 Register result_end, 4162 Register result_end,
4154 Register scratch, 4163 Register scratch,
4155 Label* gc_required, 4164 Label* gc_required,
4156 AllocationFlags flags) { 4165 AllocationFlags flags) {
4157 ASSERT((flags & SIZE_IN_WORDS) == 0); 4166 ASSERT((flags & SIZE_IN_WORDS) == 0);
4158 if (!FLAG_inline_new) { 4167 if (!FLAG_inline_new ||
4168 // TODO(mstarzinger): Implement more efficiently by keeping then
4169 // bump-pointer allocation area empty instead of recompiling code.
4170 isolate()->heap_profiler()->is_tracking_allocations()) {
4159 if (emit_debug_code()) { 4171 if (emit_debug_code()) {
4160 // Trash the registers to simulate an allocation failure. 4172 // Trash the registers to simulate an allocation failure.
4161 movl(result, Immediate(0x7091)); 4173 movl(result, Immediate(0x7091));
4162 movl(result_end, Immediate(0x7191)); 4174 movl(result_end, Immediate(0x7191));
4163 if (scratch.is_valid()) { 4175 if (scratch.is_valid()) {
4164 movl(scratch, Immediate(0x7291)); 4176 movl(scratch, Immediate(0x7291));
4165 } 4177 }
4166 // object_size is left unchanged by this function. 4178 // object_size is left unchanged by this function.
4167 } 4179 }
4168 jmp(gc_required); 4180 jmp(gc_required);
4169 return; 4181 return;
4170 } 4182 }
4171 ASSERT(!result.is(result_end)); 4183 ASSERT(!result.is(result_end));
4172 4184
4173 // Load address of new object into result. 4185 // Load address of new object into result.
4174 LoadAllocationTopHelper(result, scratch, flags); 4186 LoadAllocationTopHelper(result, scratch, flags);
4175 4187
4176 if (isolate()->heap_profiler()->is_tracking_allocations()) {
4177 RecordObjectAllocation(isolate(), result, object_size);
4178 }
4179
4180 // Align the next allocation. Storing the filler map without checking top is 4188 // Align the next allocation. Storing the filler map without checking top is
4181 // safe in new-space because the limit of the heap is aligned there. 4189 // safe in new-space because the limit of the heap is aligned there.
4182 if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) { 4190 if (((flags & DOUBLE_ALIGNMENT) != 0) && FLAG_debug_code) {
4183 testq(result, Immediate(kDoubleAlignmentMask)); 4191 testq(result, Immediate(kDoubleAlignmentMask));
4184 Check(zero, kAllocationIsNotDoubleAligned); 4192 Check(zero, kAllocationIsNotDoubleAligned);
4185 } 4193 }
4186 4194
4187 // Calculate new top and bail out if new space is exhausted. 4195 // Calculate new top and bail out if new space is exhausted.
4188 ExternalReference allocation_limit = 4196 ExternalReference allocation_limit =
4189 AllocationUtils::GetAllocationLimitReference(isolate(), flags); 4197 AllocationUtils::GetAllocationLimitReference(isolate(), flags);
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
4400 void MacroAssembler::CopyBytes(Register destination, 4408 void MacroAssembler::CopyBytes(Register destination,
4401 Register source, 4409 Register source,
4402 Register length, 4410 Register length,
4403 int min_length, 4411 int min_length,
4404 Register scratch) { 4412 Register scratch) {
4405 ASSERT(min_length >= 0); 4413 ASSERT(min_length >= 0);
4406 if (emit_debug_code()) { 4414 if (emit_debug_code()) {
4407 cmpl(length, Immediate(min_length)); 4415 cmpl(length, Immediate(min_length));
4408 Assert(greater_equal, kInvalidMinLength); 4416 Assert(greater_equal, kInvalidMinLength);
4409 } 4417 }
4410 Label loop, done, short_string, short_loop; 4418 Label short_loop, len8, len16, len24, done, short_string;
4411 4419
4412 const int kLongStringLimit = 20; 4420 const int kLongStringLimit = 4 * kPointerSize;
4413 if (min_length <= kLongStringLimit) { 4421 if (min_length <= kLongStringLimit) {
4414 cmpl(length, Immediate(kLongStringLimit)); 4422 cmpl(length, Immediate(kPointerSize));
4415 j(less_equal, &short_string); 4423 j(below, &short_string, Label::kNear);
4416 } 4424 }
4417 4425
4418 ASSERT(source.is(rsi)); 4426 ASSERT(source.is(rsi));
4419 ASSERT(destination.is(rdi)); 4427 ASSERT(destination.is(rdi));
4420 ASSERT(length.is(rcx)); 4428 ASSERT(length.is(rcx));
4421 4429
4430 if (min_length <= kLongStringLimit) {
4431 cmpl(length, Immediate(2 * kPointerSize));
4432 j(below_equal, &len8, Label::kNear);
4433 cmpl(length, Immediate(3 * kPointerSize));
4434 j(below_equal, &len16, Label::kNear);
4435 cmpl(length, Immediate(4 * kPointerSize));
4436 j(below_equal, &len24, Label::kNear);
4437 }
4438
4422 // Because source is 8-byte aligned in our uses of this function, 4439 // Because source is 8-byte aligned in our uses of this function,
4423 // we keep source aligned for the rep movs operation by copying the odd bytes 4440 // we keep source aligned for the rep movs operation by copying the odd bytes
4424 // at the end of the ranges. 4441 // at the end of the ranges.
4425 movq(scratch, length); 4442 movq(scratch, length);
4426 shrl(length, Immediate(kPointerSizeLog2)); 4443 shrl(length, Immediate(kPointerSizeLog2));
4427 repmovsq(); 4444 repmovsq();
4428 // Move remaining bytes of length. 4445 // Move remaining bytes of length.
4429 andl(scratch, Immediate(kPointerSize - 1)); 4446 andl(scratch, Immediate(kPointerSize - 1));
4430 movq(length, Operand(source, scratch, times_1, -kPointerSize)); 4447 movq(length, Operand(source, scratch, times_1, -kPointerSize));
4431 movq(Operand(destination, scratch, times_1, -kPointerSize), length); 4448 movq(Operand(destination, scratch, times_1, -kPointerSize), length);
4432 addq(destination, scratch); 4449 addq(destination, scratch);
4433 4450
4434 if (min_length <= kLongStringLimit) { 4451 if (min_length <= kLongStringLimit) {
4435 jmp(&done); 4452 jmp(&done, Label::kNear);
4453 bind(&len24);
4454 movq(scratch, Operand(source, 2 * kPointerSize));
4455 movq(Operand(destination, 2 * kPointerSize), scratch);
4456 bind(&len16);
4457 movq(scratch, Operand(source, kPointerSize));
4458 movq(Operand(destination, kPointerSize), scratch);
4459 bind(&len8);
4460 movq(scratch, Operand(source, 0));
4461 movq(Operand(destination, 0), scratch);
4462 // Move remaining bytes of length.
4463 movq(scratch, Operand(source, length, times_1, -kPointerSize));
4464 movq(Operand(destination, length, times_1, -kPointerSize), scratch);
4465 addq(destination, length);
4466 jmp(&done, Label::kNear);
4436 4467
4437 bind(&short_string); 4468 bind(&short_string);
4438 if (min_length == 0) { 4469 if (min_length == 0) {
4439 testl(length, length); 4470 testl(length, length);
4440 j(zero, &done); 4471 j(zero, &done, Label::kNear);
4441 } 4472 }
4442 lea(scratch, Operand(destination, length, times_1, 0));
4443 4473
4444 bind(&short_loop); 4474 bind(&short_loop);
4445 movb(length, Operand(source, 0)); 4475 movb(scratch, Operand(source, 0));
4446 movb(Operand(destination, 0), length); 4476 movb(Operand(destination, 0), scratch);
4447 incq(source); 4477 incq(source);
4448 incq(destination); 4478 incq(destination);
4449 cmpq(destination, scratch); 4479 decl(length);
4450 j(not_equal, &short_loop); 4480 j(not_zero, &short_loop);
4481 }
4451 4482
4452 bind(&done); 4483 bind(&done);
4453 }
4454 } 4484 }
4455 4485
4456 4486
4457 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset, 4487 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
4458 Register end_offset, 4488 Register end_offset,
4459 Register filler) { 4489 Register filler) {
4460 Label loop, entry; 4490 Label loop, entry;
4461 jmp(&entry); 4491 jmp(&entry);
4462 bind(&loop); 4492 bind(&loop);
4463 movq(Operand(start_offset, 0), filler); 4493 movq(Operand(start_offset, 0), filler);
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
4920 Register receiver_reg, 4950 Register receiver_reg,
4921 Register scratch_reg, 4951 Register scratch_reg,
4922 Label* no_memento_found) { 4952 Label* no_memento_found) {
4923 ExternalReference new_space_start = 4953 ExternalReference new_space_start =
4924 ExternalReference::new_space_start(isolate()); 4954 ExternalReference::new_space_start(isolate());
4925 ExternalReference new_space_allocation_top = 4955 ExternalReference new_space_allocation_top =
4926 ExternalReference::new_space_allocation_top_address(isolate()); 4956 ExternalReference::new_space_allocation_top_address(isolate());
4927 4957
4928 lea(scratch_reg, Operand(receiver_reg, 4958 lea(scratch_reg, Operand(receiver_reg,
4929 JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag)); 4959 JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
4930 movq(kScratchRegister, new_space_start); 4960 Move(kScratchRegister, new_space_start);
4931 cmpq(scratch_reg, kScratchRegister); 4961 cmpq(scratch_reg, kScratchRegister);
4932 j(less, no_memento_found); 4962 j(less, no_memento_found);
4933 cmpq(scratch_reg, ExternalOperand(new_space_allocation_top)); 4963 cmpq(scratch_reg, ExternalOperand(new_space_allocation_top));
4934 j(greater, no_memento_found); 4964 j(greater, no_memento_found);
4935 CompareRoot(MemOperand(scratch_reg, -AllocationMemento::kSize), 4965 CompareRoot(MemOperand(scratch_reg, -AllocationMemento::kSize),
4936 Heap::kAllocationMementoMapRootIndex); 4966 Heap::kAllocationMementoMapRootIndex);
4937 } 4967 }
4938 4968
4939 4969
4940 void MacroAssembler::RecordObjectAllocation(Isolate* isolate,
4941 Register object,
4942 Register object_size) {
4943 FrameScope frame(this, StackFrame::EXIT);
4944 PushSafepointRegisters();
4945 PrepareCallCFunction(3);
4946 // In case object is rdx
4947 movq(kScratchRegister, object);
4948 movq(arg_reg_3, object_size);
4949 movq(arg_reg_2, kScratchRegister);
4950 movq(arg_reg_1, isolate, RelocInfo::EXTERNAL_REFERENCE);
4951 CallCFunction(
4952 ExternalReference::record_object_allocation_function(isolate), 3);
4953 PopSafepointRegisters();
4954 }
4955
4956
4957 void MacroAssembler::RecordObjectAllocation(Isolate* isolate,
4958 Register object,
4959 int object_size) {
4960 FrameScope frame(this, StackFrame::EXIT);
4961 PushSafepointRegisters();
4962 PrepareCallCFunction(3);
4963 movq(arg_reg_2, object);
4964 movq(arg_reg_3, Immediate(object_size));
4965 movq(arg_reg_1, isolate, RelocInfo::EXTERNAL_REFERENCE);
4966 CallCFunction(
4967 ExternalReference::record_object_allocation_function(isolate), 3);
4968 PopSafepointRegisters();
4969 }
4970
4971
4972 void MacroAssembler::JumpIfDictionaryInPrototypeChain( 4970 void MacroAssembler::JumpIfDictionaryInPrototypeChain(
4973 Register object, 4971 Register object,
4974 Register scratch0, 4972 Register scratch0,
4975 Register scratch1, 4973 Register scratch1,
4976 Label* found) { 4974 Label* found) {
4977 ASSERT(!(scratch0.is(kScratchRegister) && scratch1.is(kScratchRegister))); 4975 ASSERT(!(scratch0.is(kScratchRegister) && scratch1.is(kScratchRegister)));
4978 ASSERT(!scratch1.is(scratch0)); 4976 ASSERT(!scratch1.is(scratch0));
4979 Register current = scratch0; 4977 Register current = scratch0;
4980 Label loop_again; 4978 Label loop_again;
4981 4979
4982 movq(current, object); 4980 movq(current, object);
4983 4981
4984 // Loop based on the map going up the prototype chain. 4982 // Loop based on the map going up the prototype chain.
4985 bind(&loop_again); 4983 bind(&loop_again);
4986 movq(current, FieldOperand(current, HeapObject::kMapOffset)); 4984 movq(current, FieldOperand(current, HeapObject::kMapOffset));
4987 movq(scratch1, FieldOperand(current, Map::kBitField2Offset)); 4985 movq(scratch1, FieldOperand(current, Map::kBitField2Offset));
4988 and_(scratch1, Immediate(Map::kElementsKindMask)); 4986 and_(scratch1, Immediate(Map::kElementsKindMask));
4989 shr(scratch1, Immediate(Map::kElementsKindShift)); 4987 shr(scratch1, Immediate(Map::kElementsKindShift));
4990 cmpq(scratch1, Immediate(DICTIONARY_ELEMENTS)); 4988 cmpq(scratch1, Immediate(DICTIONARY_ELEMENTS));
4991 j(equal, found); 4989 j(equal, found);
4992 movq(current, FieldOperand(current, Map::kPrototypeOffset)); 4990 movq(current, FieldOperand(current, Map::kPrototypeOffset));
4993 CompareRoot(current, Heap::kNullValueRootIndex); 4991 CompareRoot(current, Heap::kNullValueRootIndex);
4994 j(not_equal, &loop_again); 4992 j(not_equal, &loop_again);
4995 } 4993 }
4996 4994
4997 4995
4998 } } // namespace v8::internal 4996 } } // namespace v8::internal
4999 4997
5000 #endif // V8_TARGET_ARCH_X64 4998 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.h ('k') | src/x64/regexp-macro-assembler-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698