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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 // Compute number of region covering addr. See Page::GetRegionNumberForAddress | 70 // Compute number of region covering addr. See Page::GetRegionNumberForAddress |
71 // method for more details. | 71 // method for more details. |
72 and_(addr, Page::kPageAlignmentMask); | 72 and_(addr, Page::kPageAlignmentMask); |
73 shr(addr, Page::kRegionSizeLog2); | 73 shr(addr, Page::kRegionSizeLog2); |
74 | 74 |
75 // Set dirty mark for region. | 75 // Set dirty mark for region. |
76 bts(Operand(object, Page::kDirtyFlagOffset), addr); | 76 bts(Operand(object, Page::kDirtyFlagOffset), addr); |
77 } | 77 } |
78 | 78 |
79 | 79 |
| 80 void MacroAssembler::InNewSpace(Register object, |
| 81 Register scratch, |
| 82 Condition cc, |
| 83 Label* branch, |
| 84 Label::Distance branch_near) { |
| 85 ASSERT(cc == equal || cc == not_equal); |
| 86 if (Serializer::enabled()) { |
| 87 // Can't do arithmetic on external references if it might get serialized. |
| 88 mov(scratch, Operand(object)); |
| 89 // The mask isn't really an address. We load it as an external reference in |
| 90 // case the size of the new space is different between the snapshot maker |
| 91 // and the running system. |
| 92 and_(Operand(scratch), |
| 93 Immediate(ExternalReference::new_space_mask(isolate()))); |
| 94 cmp(Operand(scratch), |
| 95 Immediate(ExternalReference::new_space_start(isolate()))); |
| 96 j(cc, branch, branch_near); |
| 97 } else { |
| 98 int32_t new_space_start = reinterpret_cast<int32_t>( |
| 99 ExternalReference::new_space_start(isolate()).address()); |
| 100 lea(scratch, Operand(object, -new_space_start)); |
| 101 and_(scratch, isolate()->heap()->NewSpaceMask()); |
| 102 j(cc, branch, branch_near); |
| 103 } |
| 104 } |
| 105 |
| 106 |
80 void MacroAssembler::RecordWrite(Register object, | 107 void MacroAssembler::RecordWrite(Register object, |
81 int offset, | 108 int offset, |
82 Register value, | 109 Register value, |
83 Register scratch) { | 110 Register scratch) { |
84 // First, check if a write barrier is even needed. The tests below | 111 // First, check if a write barrier is even needed. The tests below |
85 // catch stores of Smis and stores into young gen. | 112 // catch stores of Smis and stores into young gen. |
86 NearLabel done; | 113 Label done; |
87 | 114 |
88 // Skip barrier if writing a smi. | 115 // Skip barrier if writing a smi. |
89 ASSERT_EQ(0, kSmiTag); | 116 ASSERT_EQ(0, kSmiTag); |
90 test(value, Immediate(kSmiTagMask)); | 117 test(value, Immediate(kSmiTagMask)); |
91 j(zero, &done); | 118 j(zero, &done, Label::kNear); |
92 | 119 |
93 InNewSpace(object, value, equal, &done); | 120 InNewSpace(object, value, equal, &done, Label::kNear); |
94 | 121 |
95 // The offset is relative to a tagged or untagged HeapObject pointer, | 122 // The offset is relative to a tagged or untagged HeapObject pointer, |
96 // so either offset or offset + kHeapObjectTag must be a | 123 // so either offset or offset + kHeapObjectTag must be a |
97 // multiple of kPointerSize. | 124 // multiple of kPointerSize. |
98 ASSERT(IsAligned(offset, kPointerSize) || | 125 ASSERT(IsAligned(offset, kPointerSize) || |
99 IsAligned(offset + kHeapObjectTag, kPointerSize)); | 126 IsAligned(offset + kHeapObjectTag, kPointerSize)); |
100 | 127 |
101 Register dst = scratch; | 128 Register dst = scratch; |
102 if (offset != 0) { | 129 if (offset != 0) { |
103 lea(dst, Operand(object, offset)); | 130 lea(dst, Operand(object, offset)); |
(...skipping 1322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1426 mov(ebx, Immediate(ext)); | 1453 mov(ebx, Immediate(ext)); |
1427 CEntryStub ces(1); | 1454 CEntryStub ces(1); |
1428 return TryTailCallStub(&ces); | 1455 return TryTailCallStub(&ces); |
1429 } | 1456 } |
1430 | 1457 |
1431 | 1458 |
1432 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 1459 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
1433 const ParameterCount& actual, | 1460 const ParameterCount& actual, |
1434 Handle<Code> code_constant, | 1461 Handle<Code> code_constant, |
1435 const Operand& code_operand, | 1462 const Operand& code_operand, |
1436 NearLabel* done, | 1463 Label* done, |
1437 InvokeFlag flag, | 1464 InvokeFlag flag, |
| 1465 Label::Distance done_near, |
1438 const CallWrapper& call_wrapper) { | 1466 const CallWrapper& call_wrapper) { |
1439 bool definitely_matches = false; | 1467 bool definitely_matches = false; |
1440 Label invoke; | 1468 Label invoke; |
1441 if (expected.is_immediate()) { | 1469 if (expected.is_immediate()) { |
1442 ASSERT(actual.is_immediate()); | 1470 ASSERT(actual.is_immediate()); |
1443 if (expected.immediate() == actual.immediate()) { | 1471 if (expected.immediate() == actual.immediate()) { |
1444 definitely_matches = true; | 1472 definitely_matches = true; |
1445 } else { | 1473 } else { |
1446 mov(eax, actual.immediate()); | 1474 mov(eax, actual.immediate()); |
1447 const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 1475 const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1481 mov(edx, Immediate(code_constant)); | 1509 mov(edx, Immediate(code_constant)); |
1482 add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); | 1510 add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag)); |
1483 } else if (!code_operand.is_reg(edx)) { | 1511 } else if (!code_operand.is_reg(edx)) { |
1484 mov(edx, code_operand); | 1512 mov(edx, code_operand); |
1485 } | 1513 } |
1486 | 1514 |
1487 if (flag == CALL_FUNCTION) { | 1515 if (flag == CALL_FUNCTION) { |
1488 call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET)); | 1516 call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET)); |
1489 call(adaptor, RelocInfo::CODE_TARGET); | 1517 call(adaptor, RelocInfo::CODE_TARGET); |
1490 call_wrapper.AfterCall(); | 1518 call_wrapper.AfterCall(); |
1491 jmp(done); | 1519 jmp(done, done_near); |
1492 } else { | 1520 } else { |
1493 jmp(adaptor, RelocInfo::CODE_TARGET); | 1521 jmp(adaptor, RelocInfo::CODE_TARGET); |
1494 } | 1522 } |
1495 bind(&invoke); | 1523 bind(&invoke); |
1496 } | 1524 } |
1497 } | 1525 } |
1498 | 1526 |
1499 | 1527 |
1500 void MacroAssembler::InvokeCode(const Operand& code, | 1528 void MacroAssembler::InvokeCode(const Operand& code, |
1501 const ParameterCount& expected, | 1529 const ParameterCount& expected, |
1502 const ParameterCount& actual, | 1530 const ParameterCount& actual, |
1503 InvokeFlag flag, | 1531 InvokeFlag flag, |
1504 const CallWrapper& call_wrapper) { | 1532 const CallWrapper& call_wrapper) { |
1505 NearLabel done; | 1533 Label done; |
1506 InvokePrologue(expected, actual, Handle<Code>::null(), code, | 1534 InvokePrologue(expected, actual, Handle<Code>::null(), code, |
1507 &done, flag, call_wrapper); | 1535 &done, flag, Label::kNear, call_wrapper); |
1508 if (flag == CALL_FUNCTION) { | 1536 if (flag == CALL_FUNCTION) { |
1509 call_wrapper.BeforeCall(CallSize(code)); | 1537 call_wrapper.BeforeCall(CallSize(code)); |
1510 call(code); | 1538 call(code); |
1511 call_wrapper.AfterCall(); | 1539 call_wrapper.AfterCall(); |
1512 } else { | 1540 } else { |
1513 ASSERT(flag == JUMP_FUNCTION); | 1541 ASSERT(flag == JUMP_FUNCTION); |
1514 jmp(code); | 1542 jmp(code); |
1515 } | 1543 } |
1516 bind(&done); | 1544 bind(&done); |
1517 } | 1545 } |
1518 | 1546 |
1519 | 1547 |
1520 void MacroAssembler::InvokeCode(Handle<Code> code, | 1548 void MacroAssembler::InvokeCode(Handle<Code> code, |
1521 const ParameterCount& expected, | 1549 const ParameterCount& expected, |
1522 const ParameterCount& actual, | 1550 const ParameterCount& actual, |
1523 RelocInfo::Mode rmode, | 1551 RelocInfo::Mode rmode, |
1524 InvokeFlag flag, | 1552 InvokeFlag flag, |
1525 const CallWrapper& call_wrapper) { | 1553 const CallWrapper& call_wrapper) { |
1526 NearLabel done; | 1554 Label done; |
1527 Operand dummy(eax); | 1555 Operand dummy(eax); |
1528 InvokePrologue(expected, actual, code, dummy, &done, flag, call_wrapper); | 1556 InvokePrologue(expected, actual, code, dummy, &done, flag, Label::kNear, |
| 1557 call_wrapper); |
1529 if (flag == CALL_FUNCTION) { | 1558 if (flag == CALL_FUNCTION) { |
1530 call_wrapper.BeforeCall(CallSize(code, rmode)); | 1559 call_wrapper.BeforeCall(CallSize(code, rmode)); |
1531 call(code, rmode); | 1560 call(code, rmode); |
1532 call_wrapper.AfterCall(); | 1561 call_wrapper.AfterCall(); |
1533 } else { | 1562 } else { |
1534 ASSERT(flag == JUMP_FUNCTION); | 1563 ASSERT(flag == JUMP_FUNCTION); |
1535 jmp(code, rmode); | 1564 jmp(code, rmode); |
1536 } | 1565 } |
1537 bind(&done); | 1566 bind(&done); |
1538 } | 1567 } |
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2036 | 2065 |
2037 // Check that the code was patched as expected. | 2066 // Check that the code was patched as expected. |
2038 ASSERT(masm_.pc_ == address_ + size_); | 2067 ASSERT(masm_.pc_ == address_ + size_); |
2039 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 2068 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
2040 } | 2069 } |
2041 | 2070 |
2042 | 2071 |
2043 } } // namespace v8::internal | 2072 } } // namespace v8::internal |
2044 | 2073 |
2045 #endif // V8_TARGET_ARCH_IA32 | 2074 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |