OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 26 matching lines...) Expand all Loading... |
37 #include "debug.h" | 37 #include "debug.h" |
38 #include "heap.h" | 38 #include "heap.h" |
39 | 39 |
40 namespace v8 { | 40 namespace v8 { |
41 namespace internal { | 41 namespace internal { |
42 | 42 |
43 MacroAssembler::MacroAssembler(void* buffer, int size) | 43 MacroAssembler::MacroAssembler(void* buffer, int size) |
44 : Assembler(buffer, size), | 44 : Assembler(buffer, size), |
45 generating_stub_(false), | 45 generating_stub_(false), |
46 allow_stub_calls_(true), | 46 allow_stub_calls_(true), |
| 47 root_array_available_(true), |
47 code_object_(HEAP->undefined_value()) { | 48 code_object_(HEAP->undefined_value()) { |
48 } | 49 } |
49 | 50 |
50 | 51 |
| 52 static intptr_t RootRegisterDelta(ExternalReference other) { |
| 53 Address roots_register_value = kRootRegisterBias + |
| 54 reinterpret_cast<Address>(Isolate::Current()->heap()->roots_address()); |
| 55 intptr_t delta = other.address() - roots_register_value; |
| 56 return delta; |
| 57 } |
| 58 |
| 59 |
| 60 Operand MacroAssembler::ExternalOperand(ExternalReference target, |
| 61 Register scratch) { |
| 62 if (root_array_available_ && !Serializer::enabled()) { |
| 63 intptr_t delta = RootRegisterDelta(target); |
| 64 if (is_int32(delta)) { |
| 65 Serializer::TooLateToEnableNow(); |
| 66 return Operand(kRootRegister, delta); |
| 67 } |
| 68 } |
| 69 movq(scratch, target); |
| 70 return Operand(scratch, 0); |
| 71 } |
| 72 |
| 73 |
| 74 void MacroAssembler::Load(Register destination, ExternalReference source) { |
| 75 if (root_array_available_ && !Serializer::enabled()) { |
| 76 intptr_t delta = RootRegisterDelta(source); |
| 77 if (is_int32(delta)) { |
| 78 Serializer::TooLateToEnableNow(); |
| 79 movq(destination, Operand(kRootRegister, static_cast<int32_t>(delta))); |
| 80 return; |
| 81 } |
| 82 } |
| 83 // Safe code. |
| 84 if (destination.is(rax)) { |
| 85 load_rax(source); |
| 86 } else { |
| 87 movq(kScratchRegister, source); |
| 88 movq(destination, Operand(kScratchRegister, 0)); |
| 89 } |
| 90 } |
| 91 |
| 92 |
| 93 void MacroAssembler::Store(ExternalReference destination, Register source) { |
| 94 if (root_array_available_ && !Serializer::enabled()) { |
| 95 intptr_t delta = RootRegisterDelta(destination); |
| 96 if (is_int32(delta)) { |
| 97 Serializer::TooLateToEnableNow(); |
| 98 movq(Operand(kRootRegister, static_cast<int32_t>(delta)), source); |
| 99 return; |
| 100 } |
| 101 } |
| 102 // Safe code. |
| 103 if (source.is(rax)) { |
| 104 store_rax(destination); |
| 105 } else { |
| 106 movq(kScratchRegister, destination); |
| 107 movq(Operand(kScratchRegister, 0), source); |
| 108 } |
| 109 } |
| 110 |
| 111 |
| 112 void MacroAssembler::LoadAddress(Register destination, |
| 113 ExternalReference source) { |
| 114 if (root_array_available_ && !Serializer::enabled()) { |
| 115 intptr_t delta = RootRegisterDelta(source); |
| 116 if (is_int32(delta)) { |
| 117 Serializer::TooLateToEnableNow(); |
| 118 lea(destination, Operand(kRootRegister, static_cast<int32_t>(delta))); |
| 119 return; |
| 120 } |
| 121 } |
| 122 // Safe code. |
| 123 movq(destination, source); |
| 124 } |
| 125 |
| 126 |
| 127 int MacroAssembler::LoadAddressSize(ExternalReference source) { |
| 128 if (root_array_available_ && !Serializer::enabled()) { |
| 129 // This calculation depends on the internals of LoadAddress. |
| 130 // It's correctness is ensured by the asserts in the Call |
| 131 // instruction below. |
| 132 intptr_t delta = RootRegisterDelta(source); |
| 133 if (is_int32(delta)) { |
| 134 Serializer::TooLateToEnableNow(); |
| 135 // Operand is lea(scratch, Operand(kRootRegister, delta)); |
| 136 // Opcodes : REX.W 8D ModRM Disp8/Disp32 - 4 or 7. |
| 137 int size = 4; |
| 138 if (!is_int8(static_cast<int32_t>(delta))) { |
| 139 size += 3; // Need full four-byte displacement in lea. |
| 140 } |
| 141 return size; |
| 142 } |
| 143 } |
| 144 // Size of movq(destination, src); |
| 145 return 10; |
| 146 } |
| 147 |
| 148 |
51 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { | 149 void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { |
| 150 ASSERT(root_array_available_); |
52 movq(destination, Operand(kRootRegister, | 151 movq(destination, Operand(kRootRegister, |
53 (index << kPointerSizeLog2) - kRootRegisterBias)); | 152 (index << kPointerSizeLog2) - kRootRegisterBias)); |
54 } | 153 } |
55 | 154 |
56 | 155 |
57 void MacroAssembler::LoadRootIndexed(Register destination, | 156 void MacroAssembler::LoadRootIndexed(Register destination, |
58 Register variable_offset, | 157 Register variable_offset, |
59 int fixed_offset) { | 158 int fixed_offset) { |
| 159 ASSERT(root_array_available_); |
60 movq(destination, | 160 movq(destination, |
61 Operand(kRootRegister, | 161 Operand(kRootRegister, |
62 variable_offset, times_pointer_size, | 162 variable_offset, times_pointer_size, |
63 (fixed_offset << kPointerSizeLog2) - kRootRegisterBias)); | 163 (fixed_offset << kPointerSizeLog2) - kRootRegisterBias)); |
64 } | 164 } |
65 | 165 |
66 | 166 |
67 void MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) { | 167 void MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index) { |
| 168 ASSERT(root_array_available_); |
68 movq(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias), | 169 movq(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias), |
69 source); | 170 source); |
70 } | 171 } |
71 | 172 |
72 | 173 |
73 void MacroAssembler::PushRoot(Heap::RootListIndex index) { | 174 void MacroAssembler::PushRoot(Heap::RootListIndex index) { |
| 175 ASSERT(root_array_available_); |
74 push(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias)); | 176 push(Operand(kRootRegister, (index << kPointerSizeLog2) - kRootRegisterBias)); |
75 } | 177 } |
76 | 178 |
77 | 179 |
78 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { | 180 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { |
| 181 ASSERT(root_array_available_); |
79 cmpq(with, Operand(kRootRegister, | 182 cmpq(with, Operand(kRootRegister, |
80 (index << kPointerSizeLog2) - kRootRegisterBias)); | 183 (index << kPointerSizeLog2) - kRootRegisterBias)); |
81 } | 184 } |
82 | 185 |
83 | 186 |
84 void MacroAssembler::CompareRoot(const Operand& with, | 187 void MacroAssembler::CompareRoot(const Operand& with, |
85 Heap::RootListIndex index) { | 188 Heap::RootListIndex index) { |
| 189 ASSERT(root_array_available_); |
86 ASSERT(!with.AddressUsesRegister(kScratchRegister)); | 190 ASSERT(!with.AddressUsesRegister(kScratchRegister)); |
87 LoadRoot(kScratchRegister, index); | 191 LoadRoot(kScratchRegister, index); |
88 cmpq(with, kScratchRegister); | 192 cmpq(with, kScratchRegister); |
89 } | 193 } |
90 | 194 |
91 | 195 |
92 void MacroAssembler::RecordWriteHelper(Register object, | 196 void MacroAssembler::RecordWriteHelper(Register object, |
93 Register addr, | 197 Register addr, |
94 Register scratch) { | 198 Register scratch) { |
95 if (emit_debug_code()) { | 199 if (emit_debug_code()) { |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 | 490 |
387 | 491 |
388 void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { | 492 void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { |
389 CallRuntime(Runtime::FunctionForId(id), num_arguments); | 493 CallRuntime(Runtime::FunctionForId(id), num_arguments); |
390 } | 494 } |
391 | 495 |
392 | 496 |
393 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) { | 497 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) { |
394 const Runtime::Function* function = Runtime::FunctionForId(id); | 498 const Runtime::Function* function = Runtime::FunctionForId(id); |
395 Set(rax, function->nargs); | 499 Set(rax, function->nargs); |
396 movq(rbx, ExternalReference(function)); | 500 LoadAddress(rbx, ExternalReference(function)); |
397 CEntryStub ces(1); | 501 CEntryStub ces(1); |
398 ces.SaveDoubles(); | 502 ces.SaveDoubles(); |
399 CallStub(&ces); | 503 CallStub(&ces); |
400 } | 504 } |
401 | 505 |
402 | 506 |
403 MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, | 507 MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, |
404 int num_arguments) { | 508 int num_arguments) { |
405 return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); | 509 return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); |
406 } | 510 } |
407 | 511 |
408 | 512 |
409 void MacroAssembler::CallRuntime(const Runtime::Function* f, | 513 void MacroAssembler::CallRuntime(const Runtime::Function* f, |
410 int num_arguments) { | 514 int num_arguments) { |
411 // If the expected number of arguments of the runtime function is | 515 // If the expected number of arguments of the runtime function is |
412 // constant, we check that the actual number of arguments match the | 516 // constant, we check that the actual number of arguments match the |
413 // expectation. | 517 // expectation. |
414 if (f->nargs >= 0 && f->nargs != num_arguments) { | 518 if (f->nargs >= 0 && f->nargs != num_arguments) { |
415 IllegalOperation(num_arguments); | 519 IllegalOperation(num_arguments); |
416 return; | 520 return; |
417 } | 521 } |
418 | 522 |
419 // TODO(1236192): Most runtime routines don't need the number of | 523 // TODO(1236192): Most runtime routines don't need the number of |
420 // arguments passed in because it is constant. At some point we | 524 // arguments passed in because it is constant. At some point we |
421 // should remove this need and make the runtime routine entry code | 525 // should remove this need and make the runtime routine entry code |
422 // smarter. | 526 // smarter. |
423 Set(rax, num_arguments); | 527 Set(rax, num_arguments); |
424 movq(rbx, ExternalReference(f)); | 528 LoadAddress(rbx, ExternalReference(f)); |
425 CEntryStub ces(f->result_size); | 529 CEntryStub ces(f->result_size); |
426 CallStub(&ces); | 530 CallStub(&ces); |
427 } | 531 } |
428 | 532 |
429 | 533 |
430 MaybeObject* MacroAssembler::TryCallRuntime(const Runtime::Function* f, | 534 MaybeObject* MacroAssembler::TryCallRuntime(const Runtime::Function* f, |
431 int num_arguments) { | 535 int num_arguments) { |
432 if (f->nargs >= 0 && f->nargs != num_arguments) { | 536 if (f->nargs >= 0 && f->nargs != num_arguments) { |
433 IllegalOperation(num_arguments); | 537 IllegalOperation(num_arguments); |
434 // Since we did not call the stub, there was no allocation failure. | 538 // Since we did not call the stub, there was no allocation failure. |
435 // Return some non-failure object. | 539 // Return some non-failure object. |
436 return HEAP->undefined_value(); | 540 return HEAP->undefined_value(); |
437 } | 541 } |
438 | 542 |
439 // TODO(1236192): Most runtime routines don't need the number of | 543 // TODO(1236192): Most runtime routines don't need the number of |
440 // arguments passed in because it is constant. At some point we | 544 // arguments passed in because it is constant. At some point we |
441 // should remove this need and make the runtime routine entry code | 545 // should remove this need and make the runtime routine entry code |
442 // smarter. | 546 // smarter. |
443 Set(rax, num_arguments); | 547 Set(rax, num_arguments); |
444 movq(rbx, ExternalReference(f)); | 548 LoadAddress(rbx, ExternalReference(f)); |
445 CEntryStub ces(f->result_size); | 549 CEntryStub ces(f->result_size); |
446 return TryCallStub(&ces); | 550 return TryCallStub(&ces); |
447 } | 551 } |
448 | 552 |
449 | 553 |
450 void MacroAssembler::CallExternalReference(const ExternalReference& ext, | 554 void MacroAssembler::CallExternalReference(const ExternalReference& ext, |
451 int num_arguments) { | 555 int num_arguments) { |
452 Set(rax, num_arguments); | 556 Set(rax, num_arguments); |
453 movq(rbx, ext); | 557 LoadAddress(rbx, ext); |
454 | 558 |
455 CEntryStub stub(1); | 559 CEntryStub stub(1); |
456 CallStub(&stub); | 560 CallStub(&stub); |
457 } | 561 } |
458 | 562 |
459 | 563 |
460 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext, | 564 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext, |
461 int num_arguments, | 565 int num_arguments, |
462 int result_size) { | 566 int result_size) { |
463 // ----------- S t a t e ------------- | 567 // ----------- S t a t e ------------- |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 bind(&empty_result); | 708 bind(&empty_result); |
605 // It was zero; the result is undefined. | 709 // It was zero; the result is undefined. |
606 Move(rax, FACTORY->undefined_value()); | 710 Move(rax, FACTORY->undefined_value()); |
607 jmp(&prologue); | 711 jmp(&prologue); |
608 | 712 |
609 // HandleScope limit has changed. Delete allocated extensions. | 713 // HandleScope limit has changed. Delete allocated extensions. |
610 bind(&delete_allocated_handles); | 714 bind(&delete_allocated_handles); |
611 movq(Operand(base_reg, kLimitOffset), prev_limit_reg); | 715 movq(Operand(base_reg, kLimitOffset), prev_limit_reg); |
612 movq(prev_limit_reg, rax); | 716 movq(prev_limit_reg, rax); |
613 #ifdef _WIN64 | 717 #ifdef _WIN64 |
614 movq(rcx, ExternalReference::isolate_address()); | 718 LoadAddress(rcx, ExternalReference::isolate_address()); |
615 #else | 719 #else |
616 movq(rdi, ExternalReference::isolate_address()); | 720 LoadAddress(rdi, ExternalReference::isolate_address()); |
617 #endif | 721 #endif |
618 movq(rax, ExternalReference::delete_handle_scope_extensions()); | 722 LoadAddress(rax, ExternalReference::delete_handle_scope_extensions()); |
619 call(rax); | 723 call(rax); |
620 movq(rax, prev_limit_reg); | 724 movq(rax, prev_limit_reg); |
621 jmp(&leave_exit_frame); | 725 jmp(&leave_exit_frame); |
622 | 726 |
623 return result; | 727 return result; |
624 } | 728 } |
625 | 729 |
626 | 730 |
627 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext, | 731 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext, |
628 int result_size) { | 732 int result_size) { |
629 // Set the entry point and jump to the C entry runtime stub. | 733 // Set the entry point and jump to the C entry runtime stub. |
630 movq(rbx, ext); | 734 LoadAddress(rbx, ext); |
631 CEntryStub ces(result_size); | 735 CEntryStub ces(result_size); |
632 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); | 736 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); |
633 } | 737 } |
634 | 738 |
635 | 739 |
636 MaybeObject* MacroAssembler::TryJumpToExternalReference( | 740 MaybeObject* MacroAssembler::TryJumpToExternalReference( |
637 const ExternalReference& ext, int result_size) { | 741 const ExternalReference& ext, int result_size) { |
638 // Set the entry point and jump to the C entry runtime stub. | 742 // Set the entry point and jump to the C entry runtime stub. |
639 movq(rbx, ext); | 743 LoadAddress(rbx, ext); |
640 CEntryStub ces(result_size); | 744 CEntryStub ces(result_size); |
641 return TryTailCallStub(&ces); | 745 return TryTailCallStub(&ces); |
642 } | 746 } |
643 | 747 |
644 | 748 |
645 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 749 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
646 InvokeFlag flag, | 750 InvokeFlag flag, |
647 CallWrapper* call_wrapper) { | 751 CallWrapper* call_wrapper) { |
648 // Calls are not allowed in some stubs. | 752 // Calls are not allowed in some stubs. |
649 ASSERT(flag == JUMP_FUNCTION || allow_stub_calls()); | 753 ASSERT(flag == JUMP_FUNCTION || allow_stub_calls()); |
(...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1436 } | 1540 } |
1437 } | 1541 } |
1438 | 1542 |
1439 | 1543 |
1440 void MacroAssembler::Test(const Operand& src, Smi* source) { | 1544 void MacroAssembler::Test(const Operand& src, Smi* source) { |
1441 testl(Operand(src, kIntSize), Immediate(source->value())); | 1545 testl(Operand(src, kIntSize), Immediate(source->value())); |
1442 } | 1546 } |
1443 | 1547 |
1444 | 1548 |
1445 void MacroAssembler::Jump(ExternalReference ext) { | 1549 void MacroAssembler::Jump(ExternalReference ext) { |
1446 movq(kScratchRegister, ext); | 1550 LoadAddress(kScratchRegister, ext); |
1447 jmp(kScratchRegister); | 1551 jmp(kScratchRegister); |
1448 } | 1552 } |
1449 | 1553 |
1450 | 1554 |
1451 void MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) { | 1555 void MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) { |
1452 movq(kScratchRegister, destination, rmode); | 1556 movq(kScratchRegister, destination, rmode); |
1453 jmp(kScratchRegister); | 1557 jmp(kScratchRegister); |
1454 } | 1558 } |
1455 | 1559 |
1456 | 1560 |
1457 void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) { | 1561 void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) { |
1458 // TODO(X64): Inline this | 1562 // TODO(X64): Inline this |
1459 jmp(code_object, rmode); | 1563 jmp(code_object, rmode); |
1460 } | 1564 } |
1461 | 1565 |
1462 | 1566 |
| 1567 int MacroAssembler::CallSize(ExternalReference ext) { |
| 1568 // Opcode for call kScratchRegister is: Rex.B FF D4 (three bytes). |
| 1569 const int kCallInstructionSize = 3; |
| 1570 return LoadAddressSize(ext) + kCallInstructionSize; |
| 1571 } |
| 1572 |
| 1573 |
1463 void MacroAssembler::Call(ExternalReference ext) { | 1574 void MacroAssembler::Call(ExternalReference ext) { |
1464 #ifdef DEBUG | 1575 #ifdef DEBUG |
1465 int pre_position = pc_offset(); | 1576 int end_position = pc_offset() + CallSize(ext); |
1466 #endif | 1577 #endif |
1467 movq(kScratchRegister, ext); | 1578 LoadAddress(kScratchRegister, ext); |
1468 call(kScratchRegister); | 1579 call(kScratchRegister); |
1469 #ifdef DEBUG | 1580 #ifdef DEBUG |
1470 int post_position = pc_offset(); | 1581 CHECK_EQ(end_position, pc_offset()); |
1471 CHECK_EQ(pre_position + CallSize(ext), post_position); | |
1472 #endif | 1582 #endif |
1473 } | 1583 } |
1474 | 1584 |
1475 | 1585 |
1476 void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { | 1586 void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) { |
1477 #ifdef DEBUG | 1587 #ifdef DEBUG |
1478 int pre_position = pc_offset(); | 1588 int end_position = pc_offset() + CallSize(destination, rmode); |
1479 #endif | 1589 #endif |
1480 movq(kScratchRegister, destination, rmode); | 1590 movq(kScratchRegister, destination, rmode); |
1481 call(kScratchRegister); | 1591 call(kScratchRegister); |
1482 #ifdef DEBUG | 1592 #ifdef DEBUG |
1483 int post_position = pc_offset(); | 1593 CHECK_EQ(pc_offset(), end_position); |
1484 CHECK_EQ(pre_position + CallSize(destination, rmode), post_position); | |
1485 #endif | 1594 #endif |
1486 } | 1595 } |
1487 | 1596 |
1488 | 1597 |
1489 void MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) { | 1598 void MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) { |
1490 #ifdef DEBUG | 1599 #ifdef DEBUG |
1491 int pre_position = pc_offset(); | 1600 int end_position = pc_offset() + CallSize(code_object); |
1492 #endif | 1601 #endif |
1493 ASSERT(RelocInfo::IsCodeTarget(rmode)); | 1602 ASSERT(RelocInfo::IsCodeTarget(rmode)); |
1494 call(code_object, rmode); | 1603 call(code_object, rmode); |
1495 #ifdef DEBUG | 1604 #ifdef DEBUG |
1496 int post_position = pc_offset(); | 1605 CHECK_EQ(end_position, pc_offset()); |
1497 CHECK_EQ(pre_position + CallSize(code_object), post_position); | |
1498 #endif | 1606 #endif |
1499 } | 1607 } |
1500 | 1608 |
1501 | 1609 |
1502 void MacroAssembler::Pushad() { | 1610 void MacroAssembler::Pushad() { |
1503 push(rax); | 1611 push(rax); |
1504 push(rcx); | 1612 push(rcx); |
1505 push(rdx); | 1613 push(rdx); |
1506 push(rbx); | 1614 push(rbx); |
1507 // Not pushing rsp or rbp. | 1615 // Not pushing rsp or rbp. |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1608 push(rbp); | 1716 push(rbp); |
1609 } else { | 1717 } else { |
1610 ASSERT(try_location == IN_JS_ENTRY); | 1718 ASSERT(try_location == IN_JS_ENTRY); |
1611 // The frame pointer does not point to a JS frame so we save NULL | 1719 // The frame pointer does not point to a JS frame so we save NULL |
1612 // for rbp. We expect the code throwing an exception to check rbp | 1720 // for rbp. We expect the code throwing an exception to check rbp |
1613 // before dereferencing it to restore the context. | 1721 // before dereferencing it to restore the context. |
1614 push(Immediate(StackHandler::ENTRY)); | 1722 push(Immediate(StackHandler::ENTRY)); |
1615 push(Immediate(0)); // NULL frame pointer. | 1723 push(Immediate(0)); // NULL frame pointer. |
1616 } | 1724 } |
1617 // Save the current handler. | 1725 // Save the current handler. |
1618 movq(kScratchRegister, ExternalReference(Isolate::k_handler_address)); | 1726 Operand handler_operand = |
1619 push(Operand(kScratchRegister, 0)); | 1727 ExternalOperand(ExternalReference(Isolate::k_handler_address)); |
| 1728 push(handler_operand); |
1620 // Link this handler. | 1729 // Link this handler. |
1621 movq(Operand(kScratchRegister, 0), rsp); | 1730 movq(handler_operand, rsp); |
1622 } | 1731 } |
1623 | 1732 |
1624 | 1733 |
1625 void MacroAssembler::PopTryHandler() { | 1734 void MacroAssembler::PopTryHandler() { |
1626 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); | 1735 ASSERT_EQ(0, StackHandlerConstants::kNextOffset); |
1627 // Unlink this handler. | 1736 // Unlink this handler. |
1628 movq(kScratchRegister, ExternalReference(Isolate::k_handler_address)); | 1737 Operand handler_operand = |
1629 pop(Operand(kScratchRegister, 0)); | 1738 ExternalOperand(ExternalReference(Isolate::k_handler_address)); |
| 1739 pop(handler_operand); |
1630 // Remove the remaining fields. | 1740 // Remove the remaining fields. |
1631 addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); | 1741 addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize)); |
1632 } | 1742 } |
1633 | 1743 |
1634 | 1744 |
1635 void MacroAssembler::Throw(Register value) { | 1745 void MacroAssembler::Throw(Register value) { |
1636 // Check that stack should contain next handler, frame pointer, state and | 1746 // Check that stack should contain next handler, frame pointer, state and |
1637 // return address in that order. | 1747 // return address in that order. |
1638 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == | 1748 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == |
1639 StackHandlerConstants::kStateOffset); | 1749 StackHandlerConstants::kStateOffset); |
1640 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == | 1750 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == |
1641 StackHandlerConstants::kPCOffset); | 1751 StackHandlerConstants::kPCOffset); |
1642 // Keep thrown value in rax. | 1752 // Keep thrown value in rax. |
1643 if (!value.is(rax)) { | 1753 if (!value.is(rax)) { |
1644 movq(rax, value); | 1754 movq(rax, value); |
1645 } | 1755 } |
1646 | 1756 |
1647 ExternalReference handler_address(Isolate::k_handler_address); | 1757 ExternalReference handler_address(Isolate::k_handler_address); |
1648 movq(kScratchRegister, handler_address); | 1758 Operand handler_operand = ExternalOperand(handler_address); |
1649 movq(rsp, Operand(kScratchRegister, 0)); | 1759 movq(rsp, handler_operand); |
1650 // get next in chain | 1760 // get next in chain |
1651 pop(rcx); | 1761 pop(handler_operand); |
1652 movq(Operand(kScratchRegister, 0), rcx); | |
1653 pop(rbp); // pop frame pointer | 1762 pop(rbp); // pop frame pointer |
1654 pop(rdx); // remove state | 1763 pop(rdx); // remove state |
1655 | 1764 |
1656 // Before returning we restore the context from the frame pointer if not NULL. | 1765 // Before returning we restore the context from the frame pointer if not NULL. |
1657 // The frame pointer is NULL in the exception handler of a JS entry frame. | 1766 // The frame pointer is NULL in the exception handler of a JS entry frame. |
1658 Set(rsi, 0); // Tentatively set context pointer to NULL | 1767 Set(rsi, 0); // Tentatively set context pointer to NULL |
1659 NearLabel skip; | 1768 NearLabel skip; |
1660 cmpq(rbp, Immediate(0)); | 1769 cmpq(rbp, Immediate(0)); |
1661 j(equal, &skip); | 1770 j(equal, &skip); |
1662 movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1771 movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1663 bind(&skip); | 1772 bind(&skip); |
1664 ret(0); | 1773 ret(0); |
1665 } | 1774 } |
1666 | 1775 |
1667 | 1776 |
1668 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, | 1777 void MacroAssembler::ThrowUncatchable(UncatchableExceptionType type, |
1669 Register value) { | 1778 Register value) { |
1670 // Keep thrown value in rax. | 1779 // Keep thrown value in rax. |
1671 if (!value.is(rax)) { | 1780 if (!value.is(rax)) { |
1672 movq(rax, value); | 1781 movq(rax, value); |
1673 } | 1782 } |
1674 // Fetch top stack handler. | 1783 // Fetch top stack handler. |
1675 ExternalReference handler_address(Isolate::k_handler_address); | 1784 ExternalReference handler_address(Isolate::k_handler_address); |
1676 movq(kScratchRegister, handler_address); | 1785 Load(rsp, handler_address); |
1677 movq(rsp, Operand(kScratchRegister, 0)); | |
1678 | 1786 |
1679 // Unwind the handlers until the ENTRY handler is found. | 1787 // Unwind the handlers until the ENTRY handler is found. |
1680 NearLabel loop, done; | 1788 NearLabel loop, done; |
1681 bind(&loop); | 1789 bind(&loop); |
1682 // Load the type of the current stack handler. | 1790 // Load the type of the current stack handler. |
1683 const int kStateOffset = StackHandlerConstants::kStateOffset; | 1791 const int kStateOffset = StackHandlerConstants::kStateOffset; |
1684 cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY)); | 1792 cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY)); |
1685 j(equal, &done); | 1793 j(equal, &done); |
1686 // Fetch the next handler in the list. | 1794 // Fetch the next handler in the list. |
1687 const int kNextOffset = StackHandlerConstants::kNextOffset; | 1795 const int kNextOffset = StackHandlerConstants::kNextOffset; |
1688 movq(rsp, Operand(rsp, kNextOffset)); | 1796 movq(rsp, Operand(rsp, kNextOffset)); |
1689 jmp(&loop); | 1797 jmp(&loop); |
1690 bind(&done); | 1798 bind(&done); |
1691 | 1799 |
1692 // Set the top handler address to next handler past the current ENTRY handler. | 1800 // Set the top handler address to next handler past the current ENTRY handler. |
1693 movq(kScratchRegister, handler_address); | 1801 Operand handler_operand = ExternalOperand(handler_address); |
1694 pop(Operand(kScratchRegister, 0)); | 1802 pop(handler_operand); |
1695 | 1803 |
1696 if (type == OUT_OF_MEMORY) { | 1804 if (type == OUT_OF_MEMORY) { |
1697 // Set external caught exception to false. | 1805 // Set external caught exception to false. |
1698 ExternalReference external_caught( | 1806 ExternalReference external_caught( |
1699 Isolate::k_external_caught_exception_address); | 1807 Isolate::k_external_caught_exception_address); |
1700 movq(rax, Immediate(false)); | 1808 movq(rax, Immediate(false)); |
1701 store_rax(external_caught); | 1809 Store(external_caught, rax); |
1702 | 1810 |
1703 // Set pending exception and rax to out of memory exception. | 1811 // Set pending exception and rax to out of memory exception. |
1704 ExternalReference pending_exception(Isolate::k_pending_exception_address); | 1812 ExternalReference pending_exception(Isolate::k_pending_exception_address); |
1705 movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); | 1813 movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE); |
1706 store_rax(pending_exception); | 1814 Store(pending_exception, rax); |
1707 } | 1815 } |
1708 | 1816 |
1709 // Clear the context pointer. | 1817 // Clear the context pointer. |
1710 Set(rsi, 0); | 1818 Set(rsi, 0); |
1711 | 1819 |
1712 // Restore registers from handler. | 1820 // Restore registers from handler. |
1713 STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize == | 1821 STATIC_ASSERT(StackHandlerConstants::kNextOffset + kPointerSize == |
1714 StackHandlerConstants::kFPOffset); | 1822 StackHandlerConstants::kFPOffset); |
1715 pop(rbp); // FP | 1823 pop(rbp); // FP |
1716 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == | 1824 STATIC_ASSERT(StackHandlerConstants::kFPOffset + kPointerSize == |
1717 StackHandlerConstants::kStateOffset); | 1825 StackHandlerConstants::kStateOffset); |
1718 pop(rdx); // State | 1826 pop(rdx); // State |
1719 | 1827 |
1720 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == | 1828 STATIC_ASSERT(StackHandlerConstants::kStateOffset + kPointerSize == |
1721 StackHandlerConstants::kPCOffset); | 1829 StackHandlerConstants::kPCOffset); |
1722 ret(0); | 1830 ret(0); |
1723 } | 1831 } |
1724 | 1832 |
1725 | 1833 |
1726 void MacroAssembler::Ret() { | 1834 void MacroAssembler::Ret() { |
1727 ret(0); | 1835 ret(0); |
1728 } | 1836 } |
1729 | 1837 |
1730 | 1838 |
1731 void MacroAssembler::Ret(int bytes_dropped, Register scratch) { | 1839 void MacroAssembler::Ret(int bytes_dropped, Register scratch) { |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1876 bind(&non_instance); | 1984 bind(&non_instance); |
1877 movq(result, FieldOperand(result, Map::kConstructorOffset)); | 1985 movq(result, FieldOperand(result, Map::kConstructorOffset)); |
1878 | 1986 |
1879 // All done. | 1987 // All done. |
1880 bind(&done); | 1988 bind(&done); |
1881 } | 1989 } |
1882 | 1990 |
1883 | 1991 |
1884 void MacroAssembler::SetCounter(StatsCounter* counter, int value) { | 1992 void MacroAssembler::SetCounter(StatsCounter* counter, int value) { |
1885 if (FLAG_native_code_counters && counter->Enabled()) { | 1993 if (FLAG_native_code_counters && counter->Enabled()) { |
1886 movq(kScratchRegister, ExternalReference(counter)); | 1994 Operand counter_operand = ExternalOperand(ExternalReference(counter)); |
1887 movl(Operand(kScratchRegister, 0), Immediate(value)); | 1995 movq(counter_operand, Immediate(value)); |
1888 } | 1996 } |
1889 } | 1997 } |
1890 | 1998 |
1891 | 1999 |
1892 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { | 2000 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { |
1893 ASSERT(value > 0); | 2001 ASSERT(value > 0); |
1894 if (FLAG_native_code_counters && counter->Enabled()) { | 2002 if (FLAG_native_code_counters && counter->Enabled()) { |
1895 movq(kScratchRegister, ExternalReference(counter)); | 2003 Operand counter_operand = ExternalOperand(ExternalReference(counter)); |
1896 Operand operand(kScratchRegister, 0); | |
1897 if (value == 1) { | 2004 if (value == 1) { |
1898 incl(operand); | 2005 incl(counter_operand); |
1899 } else { | 2006 } else { |
1900 addl(operand, Immediate(value)); | 2007 addl(counter_operand, Immediate(value)); |
1901 } | 2008 } |
1902 } | 2009 } |
1903 } | 2010 } |
1904 | 2011 |
1905 | 2012 |
1906 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { | 2013 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { |
1907 ASSERT(value > 0); | 2014 ASSERT(value > 0); |
1908 if (FLAG_native_code_counters && counter->Enabled()) { | 2015 if (FLAG_native_code_counters && counter->Enabled()) { |
1909 movq(kScratchRegister, ExternalReference(counter)); | 2016 Operand counter_operand = ExternalOperand(ExternalReference(counter)); |
1910 Operand operand(kScratchRegister, 0); | |
1911 if (value == 1) { | 2017 if (value == 1) { |
1912 decl(operand); | 2018 decl(counter_operand); |
1913 } else { | 2019 } else { |
1914 subl(operand, Immediate(value)); | 2020 subl(counter_operand, Immediate(value)); |
1915 } | 2021 } |
1916 } | 2022 } |
1917 } | 2023 } |
1918 | 2024 |
1919 | 2025 |
1920 #ifdef ENABLE_DEBUGGER_SUPPORT | 2026 #ifdef ENABLE_DEBUGGER_SUPPORT |
1921 void MacroAssembler::DebugBreak() { | 2027 void MacroAssembler::DebugBreak() { |
1922 ASSERT(allow_stub_calls()); | 2028 ASSERT(allow_stub_calls()); |
1923 Set(rax, 0); // No arguments. | 2029 Set(rax, 0); // No arguments. |
1924 movq(rbx, ExternalReference(Runtime::kDebugBreak)); | 2030 LoadAddress(rbx, ExternalReference(Runtime::kDebugBreak)); |
1925 CEntryStub ces(1); | 2031 CEntryStub ces(1); |
1926 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 2032 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
1927 } | 2033 } |
1928 #endif // ENABLE_DEBUGGER_SUPPORT | 2034 #endif // ENABLE_DEBUGGER_SUPPORT |
1929 | 2035 |
1930 | 2036 |
1931 void MacroAssembler::InvokeCode(Register code, | 2037 void MacroAssembler::InvokeCode(Register code, |
1932 const ParameterCount& expected, | 2038 const ParameterCount& expected, |
1933 const ParameterCount& actual, | 2039 const ParameterCount& actual, |
1934 InvokeFlag flag, | 2040 InvokeFlag flag, |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2068 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); | 2174 ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize); |
2069 push(Immediate(0)); // Saved entry sp, patched before call. | 2175 push(Immediate(0)); // Saved entry sp, patched before call. |
2070 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); | 2176 movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT); |
2071 push(kScratchRegister); // Accessed from EditFrame::code_slot. | 2177 push(kScratchRegister); // Accessed from EditFrame::code_slot. |
2072 | 2178 |
2073 // Save the frame pointer and the context in top. | 2179 // Save the frame pointer and the context in top. |
2074 if (save_rax) { | 2180 if (save_rax) { |
2075 movq(r14, rax); // Backup rax in callee-save register. | 2181 movq(r14, rax); // Backup rax in callee-save register. |
2076 } | 2182 } |
2077 | 2183 |
2078 movq(kScratchRegister, ExternalReference(Isolate::k_c_entry_fp_address)); | 2184 Store(ExternalReference(Isolate::k_c_entry_fp_address), rbp); |
2079 movq(Operand(kScratchRegister, 0), rbp); | 2185 Store(ExternalReference(Isolate::k_context_address), rsi); |
2080 | |
2081 movq(kScratchRegister, ExternalReference(Isolate::k_context_address)); | |
2082 movq(Operand(kScratchRegister, 0), rsi); | |
2083 } | 2186 } |
2084 | 2187 |
2085 | 2188 |
2086 void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, | 2189 void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, |
2087 bool save_doubles) { | 2190 bool save_doubles) { |
2088 #ifdef _WIN64 | 2191 #ifdef _WIN64 |
2089 const int kShadowSpace = 4; | 2192 const int kShadowSpace = 4; |
2090 arg_stack_space += kShadowSpace; | 2193 arg_stack_space += kShadowSpace; |
2091 #endif | 2194 #endif |
2092 // Optionally save all XMM registers. | 2195 // Optionally save all XMM registers. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2164 movq(rsp, rbp); | 2267 movq(rsp, rbp); |
2165 pop(rbp); | 2268 pop(rbp); |
2166 | 2269 |
2167 LeaveExitFrameEpilogue(); | 2270 LeaveExitFrameEpilogue(); |
2168 } | 2271 } |
2169 | 2272 |
2170 | 2273 |
2171 void MacroAssembler::LeaveExitFrameEpilogue() { | 2274 void MacroAssembler::LeaveExitFrameEpilogue() { |
2172 // Restore current context from top and clear it in debug mode. | 2275 // Restore current context from top and clear it in debug mode. |
2173 ExternalReference context_address(Isolate::k_context_address); | 2276 ExternalReference context_address(Isolate::k_context_address); |
2174 movq(kScratchRegister, context_address); | 2277 Operand context_operand = ExternalOperand(context_address); |
2175 movq(rsi, Operand(kScratchRegister, 0)); | 2278 movq(rsi, context_operand); |
2176 #ifdef DEBUG | 2279 #ifdef DEBUG |
2177 movq(Operand(kScratchRegister, 0), Immediate(0)); | 2280 movq(context_operand, Immediate(0)); |
2178 #endif | 2281 #endif |
2179 | 2282 |
2180 // Clear the top frame. | 2283 // Clear the top frame. |
2181 ExternalReference c_entry_fp_address(Isolate::k_c_entry_fp_address); | 2284 ExternalReference c_entry_fp_address(Isolate::k_c_entry_fp_address); |
2182 movq(kScratchRegister, c_entry_fp_address); | 2285 Operand c_entry_fp_operand = ExternalOperand(c_entry_fp_address); |
2183 movq(Operand(kScratchRegister, 0), Immediate(0)); | 2286 movq(c_entry_fp_operand, Immediate(0)); |
2184 } | 2287 } |
2185 | 2288 |
2186 | 2289 |
2187 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 2290 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
2188 Register scratch, | 2291 Register scratch, |
2189 Label* miss) { | 2292 Label* miss) { |
2190 Label same_contexts; | 2293 Label same_contexts; |
2191 | 2294 |
2192 ASSERT(!holder_reg.is(scratch)); | 2295 ASSERT(!holder_reg.is(scratch)); |
2193 ASSERT(!scratch.is(kScratchRegister)); | 2296 ASSERT(!scratch.is(kScratchRegister)); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2252 AllocationFlags flags) { | 2355 AllocationFlags flags) { |
2253 ExternalReference new_space_allocation_top = | 2356 ExternalReference new_space_allocation_top = |
2254 ExternalReference::new_space_allocation_top_address(); | 2357 ExternalReference::new_space_allocation_top_address(); |
2255 | 2358 |
2256 // Just return if allocation top is already known. | 2359 // Just return if allocation top is already known. |
2257 if ((flags & RESULT_CONTAINS_TOP) != 0) { | 2360 if ((flags & RESULT_CONTAINS_TOP) != 0) { |
2258 // No use of scratch if allocation top is provided. | 2361 // No use of scratch if allocation top is provided. |
2259 ASSERT(!scratch.is_valid()); | 2362 ASSERT(!scratch.is_valid()); |
2260 #ifdef DEBUG | 2363 #ifdef DEBUG |
2261 // Assert that result actually contains top on entry. | 2364 // Assert that result actually contains top on entry. |
2262 movq(kScratchRegister, new_space_allocation_top); | 2365 Operand top_operand = ExternalOperand(new_space_allocation_top); |
2263 cmpq(result, Operand(kScratchRegister, 0)); | 2366 cmpq(result, top_operand); |
2264 Check(equal, "Unexpected allocation top"); | 2367 Check(equal, "Unexpected allocation top"); |
2265 #endif | 2368 #endif |
2266 return; | 2369 return; |
2267 } | 2370 } |
2268 | 2371 |
2269 // Move address of new object to result. Use scratch register if available, | 2372 // Move address of new object to result. Use scratch register if available, |
2270 // and keep address in scratch until call to UpdateAllocationTopHelper. | 2373 // and keep address in scratch until call to UpdateAllocationTopHelper. |
2271 if (scratch.is_valid()) { | 2374 if (scratch.is_valid()) { |
2272 movq(scratch, new_space_allocation_top); | 2375 LoadAddress(scratch, new_space_allocation_top); |
2273 movq(result, Operand(scratch, 0)); | 2376 movq(result, Operand(scratch, 0)); |
2274 } else if (result.is(rax)) { | |
2275 load_rax(new_space_allocation_top); | |
2276 } else { | 2377 } else { |
2277 movq(kScratchRegister, new_space_allocation_top); | 2378 Load(result, new_space_allocation_top); |
2278 movq(result, Operand(kScratchRegister, 0)); | |
2279 } | 2379 } |
2280 } | 2380 } |
2281 | 2381 |
2282 | 2382 |
2283 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, | 2383 void MacroAssembler::UpdateAllocationTopHelper(Register result_end, |
2284 Register scratch) { | 2384 Register scratch) { |
2285 if (emit_debug_code()) { | 2385 if (emit_debug_code()) { |
2286 testq(result_end, Immediate(kObjectAlignmentMask)); | 2386 testq(result_end, Immediate(kObjectAlignmentMask)); |
2287 Check(zero, "Unaligned allocation in new space"); | 2387 Check(zero, "Unaligned allocation in new space"); |
2288 } | 2388 } |
2289 | 2389 |
2290 ExternalReference new_space_allocation_top = | 2390 ExternalReference new_space_allocation_top = |
2291 ExternalReference::new_space_allocation_top_address(); | 2391 ExternalReference::new_space_allocation_top_address(); |
2292 | 2392 |
2293 // Update new top. | 2393 // Update new top. |
2294 if (result_end.is(rax)) { | 2394 if (scratch.is_valid()) { |
2295 // rax can be stored directly to a memory location. | 2395 // Scratch already contains address of allocation top. |
2296 store_rax(new_space_allocation_top); | 2396 movq(Operand(scratch, 0), result_end); |
2297 } else { | 2397 } else { |
2298 // Register required - use scratch provided if available. | 2398 Store(new_space_allocation_top, result_end); |
2299 if (scratch.is_valid()) { | |
2300 movq(Operand(scratch, 0), result_end); | |
2301 } else { | |
2302 movq(kScratchRegister, new_space_allocation_top); | |
2303 movq(Operand(kScratchRegister, 0), result_end); | |
2304 } | |
2305 } | 2399 } |
2306 } | 2400 } |
2307 | 2401 |
2308 | 2402 |
2309 void MacroAssembler::AllocateInNewSpace(int object_size, | 2403 void MacroAssembler::AllocateInNewSpace(int object_size, |
2310 Register result, | 2404 Register result, |
2311 Register result_end, | 2405 Register result_end, |
2312 Register scratch, | 2406 Register scratch, |
2313 Label* gc_required, | 2407 Label* gc_required, |
2314 AllocationFlags flags) { | 2408 AllocationFlags flags) { |
(...skipping 20 matching lines...) Expand all Loading... |
2335 ExternalReference new_space_allocation_limit = | 2429 ExternalReference new_space_allocation_limit = |
2336 ExternalReference::new_space_allocation_limit_address(); | 2430 ExternalReference::new_space_allocation_limit_address(); |
2337 | 2431 |
2338 Register top_reg = result_end.is_valid() ? result_end : result; | 2432 Register top_reg = result_end.is_valid() ? result_end : result; |
2339 | 2433 |
2340 if (!top_reg.is(result)) { | 2434 if (!top_reg.is(result)) { |
2341 movq(top_reg, result); | 2435 movq(top_reg, result); |
2342 } | 2436 } |
2343 addq(top_reg, Immediate(object_size)); | 2437 addq(top_reg, Immediate(object_size)); |
2344 j(carry, gc_required); | 2438 j(carry, gc_required); |
2345 movq(kScratchRegister, new_space_allocation_limit); | 2439 Operand limit_operand = ExternalOperand(new_space_allocation_limit); |
2346 cmpq(top_reg, Operand(kScratchRegister, 0)); | 2440 cmpq(top_reg, limit_operand); |
2347 j(above, gc_required); | 2441 j(above, gc_required); |
2348 | 2442 |
2349 // Update allocation top. | 2443 // Update allocation top. |
2350 UpdateAllocationTopHelper(top_reg, scratch); | 2444 UpdateAllocationTopHelper(top_reg, scratch); |
2351 | 2445 |
2352 if (top_reg.is(result)) { | 2446 if (top_reg.is(result)) { |
2353 if ((flags & TAG_OBJECT) != 0) { | 2447 if ((flags & TAG_OBJECT) != 0) { |
2354 subq(result, Immediate(object_size - kHeapObjectTag)); | 2448 subq(result, Immediate(object_size - kHeapObjectTag)); |
2355 } else { | 2449 } else { |
2356 subq(result, Immediate(object_size)); | 2450 subq(result, Immediate(object_size)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2390 | 2484 |
2391 // Calculate new top and bail out if new space is exhausted. | 2485 // Calculate new top and bail out if new space is exhausted. |
2392 ExternalReference new_space_allocation_limit = | 2486 ExternalReference new_space_allocation_limit = |
2393 ExternalReference::new_space_allocation_limit_address(); | 2487 ExternalReference::new_space_allocation_limit_address(); |
2394 | 2488 |
2395 // We assume that element_count*element_size + header_size does not | 2489 // We assume that element_count*element_size + header_size does not |
2396 // overflow. | 2490 // overflow. |
2397 lea(result_end, Operand(element_count, element_size, header_size)); | 2491 lea(result_end, Operand(element_count, element_size, header_size)); |
2398 addq(result_end, result); | 2492 addq(result_end, result); |
2399 j(carry, gc_required); | 2493 j(carry, gc_required); |
2400 movq(kScratchRegister, new_space_allocation_limit); | 2494 Operand limit_operand = ExternalOperand(new_space_allocation_limit); |
2401 cmpq(result_end, Operand(kScratchRegister, 0)); | 2495 cmpq(result_end, limit_operand); |
2402 j(above, gc_required); | 2496 j(above, gc_required); |
2403 | 2497 |
2404 // Update allocation top. | 2498 // Update allocation top. |
2405 UpdateAllocationTopHelper(result_end, scratch); | 2499 UpdateAllocationTopHelper(result_end, scratch); |
2406 | 2500 |
2407 // Tag the result if requested. | 2501 // Tag the result if requested. |
2408 if ((flags & TAG_OBJECT) != 0) { | 2502 if ((flags & TAG_OBJECT) != 0) { |
2409 addq(result, Immediate(kHeapObjectTag)); | 2503 addq(result, Immediate(kHeapObjectTag)); |
2410 } | 2504 } |
2411 } | 2505 } |
(...skipping 24 matching lines...) Expand all Loading... |
2436 LoadAllocationTopHelper(result, scratch, flags); | 2530 LoadAllocationTopHelper(result, scratch, flags); |
2437 | 2531 |
2438 // Calculate new top and bail out if new space is exhausted. | 2532 // Calculate new top and bail out if new space is exhausted. |
2439 ExternalReference new_space_allocation_limit = | 2533 ExternalReference new_space_allocation_limit = |
2440 ExternalReference::new_space_allocation_limit_address(); | 2534 ExternalReference::new_space_allocation_limit_address(); |
2441 if (!object_size.is(result_end)) { | 2535 if (!object_size.is(result_end)) { |
2442 movq(result_end, object_size); | 2536 movq(result_end, object_size); |
2443 } | 2537 } |
2444 addq(result_end, result); | 2538 addq(result_end, result); |
2445 j(carry, gc_required); | 2539 j(carry, gc_required); |
2446 movq(kScratchRegister, new_space_allocation_limit); | 2540 Operand limit_operand = ExternalOperand(new_space_allocation_limit); |
2447 cmpq(result_end, Operand(kScratchRegister, 0)); | 2541 cmpq(result_end, limit_operand); |
2448 j(above, gc_required); | 2542 j(above, gc_required); |
2449 | 2543 |
2450 // Update allocation top. | 2544 // Update allocation top. |
2451 UpdateAllocationTopHelper(result_end, scratch); | 2545 UpdateAllocationTopHelper(result_end, scratch); |
2452 | 2546 |
2453 // Tag the result if requested. | 2547 // Tag the result if requested. |
2454 if ((flags & TAG_OBJECT) != 0) { | 2548 if ((flags & TAG_OBJECT) != 0) { |
2455 addq(result, Immediate(kHeapObjectTag)); | 2549 addq(result, Immediate(kHeapObjectTag)); |
2456 } | 2550 } |
2457 } | 2551 } |
2458 | 2552 |
2459 | 2553 |
2460 void MacroAssembler::UndoAllocationInNewSpace(Register object) { | 2554 void MacroAssembler::UndoAllocationInNewSpace(Register object) { |
2461 ExternalReference new_space_allocation_top = | 2555 ExternalReference new_space_allocation_top = |
2462 ExternalReference::new_space_allocation_top_address(); | 2556 ExternalReference::new_space_allocation_top_address(); |
2463 | 2557 |
2464 // Make sure the object has no tag before resetting top. | 2558 // Make sure the object has no tag before resetting top. |
2465 and_(object, Immediate(~kHeapObjectTagMask)); | 2559 and_(object, Immediate(~kHeapObjectTagMask)); |
2466 movq(kScratchRegister, new_space_allocation_top); | 2560 Operand top_operand = ExternalOperand(new_space_allocation_top); |
2467 #ifdef DEBUG | 2561 #ifdef DEBUG |
2468 cmpq(object, Operand(kScratchRegister, 0)); | 2562 cmpq(object, top_operand); |
2469 Check(below, "Undo allocation of non allocated memory"); | 2563 Check(below, "Undo allocation of non allocated memory"); |
2470 #endif | 2564 #endif |
2471 movq(Operand(kScratchRegister, 0), object); | 2565 movq(top_operand, object); |
2472 } | 2566 } |
2473 | 2567 |
2474 | 2568 |
2475 void MacroAssembler::AllocateHeapNumber(Register result, | 2569 void MacroAssembler::AllocateHeapNumber(Register result, |
2476 Register scratch, | 2570 Register scratch, |
2477 Label* gc_required) { | 2571 Label* gc_required) { |
2478 // Allocate heap number in new space. | 2572 // Allocate heap number in new space. |
2479 AllocateInNewSpace(HeapNumber::kSize, | 2573 AllocateInNewSpace(HeapNumber::kSize, |
2480 result, | 2574 result, |
2481 scratch, | 2575 scratch, |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2696 int argument_slots_on_stack = | 2790 int argument_slots_on_stack = |
2697 ArgumentStackSlotsForCFunctionCall(num_arguments); | 2791 ArgumentStackSlotsForCFunctionCall(num_arguments); |
2698 subq(rsp, Immediate((argument_slots_on_stack + 1) * kPointerSize)); | 2792 subq(rsp, Immediate((argument_slots_on_stack + 1) * kPointerSize)); |
2699 and_(rsp, Immediate(-frame_alignment)); | 2793 and_(rsp, Immediate(-frame_alignment)); |
2700 movq(Operand(rsp, argument_slots_on_stack * kPointerSize), kScratchRegister); | 2794 movq(Operand(rsp, argument_slots_on_stack * kPointerSize), kScratchRegister); |
2701 } | 2795 } |
2702 | 2796 |
2703 | 2797 |
2704 void MacroAssembler::CallCFunction(ExternalReference function, | 2798 void MacroAssembler::CallCFunction(ExternalReference function, |
2705 int num_arguments) { | 2799 int num_arguments) { |
2706 movq(rax, function); | 2800 LoadAddress(rax, function); |
2707 CallCFunction(rax, num_arguments); | 2801 CallCFunction(rax, num_arguments); |
2708 } | 2802 } |
2709 | 2803 |
2710 | 2804 |
2711 void MacroAssembler::CallCFunction(Register function, int num_arguments) { | 2805 void MacroAssembler::CallCFunction(Register function, int num_arguments) { |
2712 // Pass current isolate address as additional parameter. | 2806 // Pass current isolate address as additional parameter. |
2713 if (num_arguments < kRegisterPassedArguments) { | 2807 if (num_arguments < kRegisterPassedArguments) { |
2714 #ifdef _WIN64 | 2808 #ifdef _WIN64 |
2715 // First four arguments are passed in registers on Windows. | 2809 // First four arguments are passed in registers on Windows. |
2716 Register arg_to_reg[] = {rcx, rdx, r8, r9}; | 2810 Register arg_to_reg[] = {rcx, rdx, r8, r9}; |
2717 #else | 2811 #else |
2718 // First six arguments are passed in registers on other platforms. | 2812 // First six arguments are passed in registers on other platforms. |
2719 Register arg_to_reg[] = {rdi, rsi, rdx, rcx, r8, r9}; | 2813 Register arg_to_reg[] = {rdi, rsi, rdx, rcx, r8, r9}; |
2720 #endif | 2814 #endif |
2721 Register reg = arg_to_reg[num_arguments]; | 2815 Register reg = arg_to_reg[num_arguments]; |
2722 movq(reg, ExternalReference::isolate_address()); | 2816 LoadAddress(reg, ExternalReference::isolate_address()); |
2723 } else { | 2817 } else { |
2724 // Push Isolate pointer after all parameters. | 2818 // Push Isolate pointer after all parameters. |
2725 int argument_slots_on_stack = | 2819 int argument_slots_on_stack = |
2726 ArgumentStackSlotsForCFunctionCall(num_arguments); | 2820 ArgumentStackSlotsForCFunctionCall(num_arguments); |
2727 movq(kScratchRegister, ExternalReference::isolate_address()); | 2821 LoadAddress(kScratchRegister, ExternalReference::isolate_address()); |
2728 movq(Operand(rsp, argument_slots_on_stack * kPointerSize), | 2822 movq(Operand(rsp, argument_slots_on_stack * kPointerSize), |
2729 kScratchRegister); | 2823 kScratchRegister); |
2730 } | 2824 } |
2731 | 2825 |
2732 // Check stack alignment. | 2826 // Check stack alignment. |
2733 if (emit_debug_code()) { | 2827 if (emit_debug_code()) { |
2734 CheckStackAlignment(); | 2828 CheckStackAlignment(); |
2735 } | 2829 } |
2736 | 2830 |
2737 call(function); | 2831 call(function); |
(...skipping 20 matching lines...) Expand all Loading... |
2758 CPU::FlushICache(address_, size_); | 2852 CPU::FlushICache(address_, size_); |
2759 | 2853 |
2760 // Check that the code was patched as expected. | 2854 // Check that the code was patched as expected. |
2761 ASSERT(masm_.pc_ == address_ + size_); | 2855 ASSERT(masm_.pc_ == address_ + size_); |
2762 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2856 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
2763 } | 2857 } |
2764 | 2858 |
2765 } } // namespace v8::internal | 2859 } } // namespace v8::internal |
2766 | 2860 |
2767 #endif // V8_TARGET_ARCH_X64 | 2861 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |