OLD | NEW |
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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 allow_stub_calls_(true), | 46 allow_stub_calls_(true), |
47 has_frame_(false), | 47 has_frame_(false), |
48 root_array_available_(true) { | 48 root_array_available_(true) { |
49 if (isolate() != NULL) { | 49 if (isolate() != NULL) { |
50 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), | 50 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), |
51 isolate()); | 51 isolate()); |
52 } | 52 } |
53 } | 53 } |
54 | 54 |
55 | 55 |
56 static intptr_t RootRegisterDelta(ExternalReference other, Isolate* isolate) { | 56 static const int kInvalidRootRegisterDelta = -1; |
| 57 |
| 58 |
| 59 intptr_t MacroAssembler::RootRegisterDelta(ExternalReference other) { |
| 60 if (predictable_code_size() && |
| 61 (other.address() < reinterpret_cast<Address>(isolate()) || |
| 62 other.address() >= reinterpret_cast<Address>(isolate() + 1))) { |
| 63 return kInvalidRootRegisterDelta; |
| 64 } |
57 Address roots_register_value = kRootRegisterBias + | 65 Address roots_register_value = kRootRegisterBias + |
58 reinterpret_cast<Address>(isolate->heap()->roots_array_start()); | 66 reinterpret_cast<Address>(isolate()->heap()->roots_array_start()); |
59 intptr_t delta = other.address() - roots_register_value; | 67 intptr_t delta = other.address() - roots_register_value; |
60 return delta; | 68 return delta; |
61 } | 69 } |
62 | 70 |
63 | 71 |
64 Operand MacroAssembler::ExternalOperand(ExternalReference target, | 72 Operand MacroAssembler::ExternalOperand(ExternalReference target, |
65 Register scratch) { | 73 Register scratch) { |
66 if (root_array_available_ && !Serializer::enabled()) { | 74 if (root_array_available_ && !Serializer::enabled()) { |
67 intptr_t delta = RootRegisterDelta(target, isolate()); | 75 intptr_t delta = RootRegisterDelta(target); |
68 if (is_int32(delta)) { | 76 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) { |
69 Serializer::TooLateToEnableNow(); | 77 Serializer::TooLateToEnableNow(); |
70 return Operand(kRootRegister, static_cast<int32_t>(delta)); | 78 return Operand(kRootRegister, static_cast<int32_t>(delta)); |
71 } | 79 } |
72 } | 80 } |
73 movq(scratch, target); | 81 movq(scratch, target); |
74 return Operand(scratch, 0); | 82 return Operand(scratch, 0); |
75 } | 83 } |
76 | 84 |
77 | 85 |
78 void MacroAssembler::Load(Register destination, ExternalReference source) { | 86 void MacroAssembler::Load(Register destination, ExternalReference source) { |
79 if (root_array_available_ && !Serializer::enabled()) { | 87 if (root_array_available_ && !Serializer::enabled()) { |
80 intptr_t delta = RootRegisterDelta(source, isolate()); | 88 intptr_t delta = RootRegisterDelta(source); |
81 if (is_int32(delta)) { | 89 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) { |
82 Serializer::TooLateToEnableNow(); | 90 Serializer::TooLateToEnableNow(); |
83 movq(destination, Operand(kRootRegister, static_cast<int32_t>(delta))); | 91 movq(destination, Operand(kRootRegister, static_cast<int32_t>(delta))); |
84 return; | 92 return; |
85 } | 93 } |
86 } | 94 } |
87 // Safe code. | 95 // Safe code. |
88 if (destination.is(rax)) { | 96 if (destination.is(rax)) { |
89 load_rax(source); | 97 load_rax(source); |
90 } else { | 98 } else { |
91 movq(kScratchRegister, source); | 99 movq(kScratchRegister, source); |
92 movq(destination, Operand(kScratchRegister, 0)); | 100 movq(destination, Operand(kScratchRegister, 0)); |
93 } | 101 } |
94 } | 102 } |
95 | 103 |
96 | 104 |
97 void MacroAssembler::Store(ExternalReference destination, Register source) { | 105 void MacroAssembler::Store(ExternalReference destination, Register source) { |
98 if (root_array_available_ && !Serializer::enabled()) { | 106 if (root_array_available_ && !Serializer::enabled()) { |
99 intptr_t delta = RootRegisterDelta(destination, isolate()); | 107 intptr_t delta = RootRegisterDelta(destination); |
100 if (is_int32(delta)) { | 108 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) { |
101 Serializer::TooLateToEnableNow(); | 109 Serializer::TooLateToEnableNow(); |
102 movq(Operand(kRootRegister, static_cast<int32_t>(delta)), source); | 110 movq(Operand(kRootRegister, static_cast<int32_t>(delta)), source); |
103 return; | 111 return; |
104 } | 112 } |
105 } | 113 } |
106 // Safe code. | 114 // Safe code. |
107 if (source.is(rax)) { | 115 if (source.is(rax)) { |
108 store_rax(destination); | 116 store_rax(destination); |
109 } else { | 117 } else { |
110 movq(kScratchRegister, destination); | 118 movq(kScratchRegister, destination); |
111 movq(Operand(kScratchRegister, 0), source); | 119 movq(Operand(kScratchRegister, 0), source); |
112 } | 120 } |
113 } | 121 } |
114 | 122 |
115 | 123 |
116 void MacroAssembler::LoadAddress(Register destination, | 124 void MacroAssembler::LoadAddress(Register destination, |
117 ExternalReference source) { | 125 ExternalReference source) { |
118 if (root_array_available_ && !Serializer::enabled()) { | 126 if (root_array_available_ && !Serializer::enabled()) { |
119 intptr_t delta = RootRegisterDelta(source, isolate()); | 127 intptr_t delta = RootRegisterDelta(source); |
120 if (is_int32(delta)) { | 128 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) { |
121 Serializer::TooLateToEnableNow(); | 129 Serializer::TooLateToEnableNow(); |
122 lea(destination, Operand(kRootRegister, static_cast<int32_t>(delta))); | 130 lea(destination, Operand(kRootRegister, static_cast<int32_t>(delta))); |
123 return; | 131 return; |
124 } | 132 } |
125 } | 133 } |
126 // Safe code. | 134 // Safe code. |
127 movq(destination, source); | 135 movq(destination, source); |
128 } | 136 } |
129 | 137 |
130 | 138 |
131 int MacroAssembler::LoadAddressSize(ExternalReference source) { | 139 int MacroAssembler::LoadAddressSize(ExternalReference source) { |
132 if (root_array_available_ && !Serializer::enabled()) { | 140 if (root_array_available_ && !Serializer::enabled()) { |
133 // This calculation depends on the internals of LoadAddress. | 141 // This calculation depends on the internals of LoadAddress. |
134 // It's correctness is ensured by the asserts in the Call | 142 // It's correctness is ensured by the asserts in the Call |
135 // instruction below. | 143 // instruction below. |
136 intptr_t delta = RootRegisterDelta(source, isolate()); | 144 intptr_t delta = RootRegisterDelta(source); |
137 if (is_int32(delta)) { | 145 if (delta != kInvalidRootRegisterDelta && is_int32(delta)) { |
138 Serializer::TooLateToEnableNow(); | 146 Serializer::TooLateToEnableNow(); |
139 // Operand is lea(scratch, Operand(kRootRegister, delta)); | 147 // Operand is lea(scratch, Operand(kRootRegister, delta)); |
140 // Opcodes : REX.W 8D ModRM Disp8/Disp32 - 4 or 7. | 148 // Opcodes : REX.W 8D ModRM Disp8/Disp32 - 4 or 7. |
141 int size = 4; | 149 int size = 4; |
142 if (!is_int8(static_cast<int32_t>(delta))) { | 150 if (!is_int8(static_cast<int32_t>(delta))) { |
143 size += 3; // Need full four-byte displacement in lea. | 151 size += 3; // Need full four-byte displacement in lea. |
144 } | 152 } |
145 return size; | 153 return size; |
146 } | 154 } |
147 } | 155 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 LoadRoot(kScratchRegister, index); | 217 LoadRoot(kScratchRegister, index); |
210 cmpq(with, kScratchRegister); | 218 cmpq(with, kScratchRegister); |
211 } | 219 } |
212 | 220 |
213 | 221 |
214 void MacroAssembler::RememberedSetHelper(Register object, // For debug tests. | 222 void MacroAssembler::RememberedSetHelper(Register object, // For debug tests. |
215 Register addr, | 223 Register addr, |
216 Register scratch, | 224 Register scratch, |
217 SaveFPRegsMode save_fp, | 225 SaveFPRegsMode save_fp, |
218 RememberedSetFinalAction and_then) { | 226 RememberedSetFinalAction and_then) { |
219 if (FLAG_debug_code) { | 227 if (emit_debug_code()) { |
220 Label ok; | 228 Label ok; |
221 JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear); | 229 JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear); |
222 int3(); | 230 int3(); |
223 bind(&ok); | 231 bind(&ok); |
224 } | 232 } |
225 // Load store buffer top. | 233 // Load store buffer top. |
226 LoadRoot(scratch, Heap::kStoreBufferTopRootIndex); | 234 LoadRoot(scratch, Heap::kStoreBufferTopRootIndex); |
227 // Store pointer to buffer. | 235 // Store pointer to buffer. |
228 movq(Operand(scratch, 0), addr); | 236 movq(Operand(scratch, 0), addr); |
229 // Increment buffer top. | 237 // Increment buffer top. |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 ASSERT(!value.is(address)); | 398 ASSERT(!value.is(address)); |
391 if (emit_debug_code()) { | 399 if (emit_debug_code()) { |
392 AbortIfSmi(object); | 400 AbortIfSmi(object); |
393 } | 401 } |
394 | 402 |
395 if (remembered_set_action == OMIT_REMEMBERED_SET && | 403 if (remembered_set_action == OMIT_REMEMBERED_SET && |
396 !FLAG_incremental_marking) { | 404 !FLAG_incremental_marking) { |
397 return; | 405 return; |
398 } | 406 } |
399 | 407 |
400 if (FLAG_debug_code) { | 408 if (emit_debug_code()) { |
401 Label ok; | 409 Label ok; |
402 cmpq(value, Operand(address, 0)); | 410 cmpq(value, Operand(address, 0)); |
403 j(equal, &ok, Label::kNear); | 411 j(equal, &ok, Label::kNear); |
404 int3(); | 412 int3(); |
405 bind(&ok); | 413 bind(&ok); |
406 } | 414 } |
407 | 415 |
408 // First, check if a write barrier is even needed. The tests below | 416 // First, check if a write barrier is even needed. The tests below |
409 // catch stores of smis and stores into the young generation. | 417 // catch stores of smis and stores into the young generation. |
410 Label done; | 418 Label done; |
(...skipping 3574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3985 // clobbered. | 3993 // clobbered. |
3986 // A simpler loop is faster on small copies, but slower on large ones. | 3994 // A simpler loop is faster on small copies, but slower on large ones. |
3987 // The cld() instruction must have been emitted, to set the direction flag(), | 3995 // The cld() instruction must have been emitted, to set the direction flag(), |
3988 // before calling this function. | 3996 // before calling this function. |
3989 void MacroAssembler::CopyBytes(Register destination, | 3997 void MacroAssembler::CopyBytes(Register destination, |
3990 Register source, | 3998 Register source, |
3991 Register length, | 3999 Register length, |
3992 int min_length, | 4000 int min_length, |
3993 Register scratch) { | 4001 Register scratch) { |
3994 ASSERT(min_length >= 0); | 4002 ASSERT(min_length >= 0); |
3995 if (FLAG_debug_code) { | 4003 if (emit_debug_code()) { |
3996 cmpl(length, Immediate(min_length)); | 4004 cmpl(length, Immediate(min_length)); |
3997 Assert(greater_equal, "Invalid min_length"); | 4005 Assert(greater_equal, "Invalid min_length"); |
3998 } | 4006 } |
3999 Label loop, done, short_string, short_loop; | 4007 Label loop, done, short_string, short_loop; |
4000 | 4008 |
4001 const int kLongStringLimit = 20; | 4009 const int kLongStringLimit = 20; |
4002 if (min_length <= kLongStringLimit) { | 4010 if (min_length <= kLongStringLimit) { |
4003 cmpl(length, Immediate(kLongStringLimit)); | 4011 cmpl(length, Immediate(kLongStringLimit)); |
4004 j(less_equal, &short_string); | 4012 j(less_equal, &short_string); |
4005 } | 4013 } |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4362 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); | 4370 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); |
4363 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 4371 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
4364 | 4372 |
4365 Label done; | 4373 Label done; |
4366 | 4374 |
4367 // Since both black and grey have a 1 in the first position and white does | 4375 // Since both black and grey have a 1 in the first position and white does |
4368 // not have a 1 there we only need to check one bit. | 4376 // not have a 1 there we only need to check one bit. |
4369 testq(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); | 4377 testq(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); |
4370 j(not_zero, &done, Label::kNear); | 4378 j(not_zero, &done, Label::kNear); |
4371 | 4379 |
4372 if (FLAG_debug_code) { | 4380 if (emit_debug_code()) { |
4373 // Check for impossible bit pattern. | 4381 // Check for impossible bit pattern. |
4374 Label ok; | 4382 Label ok; |
4375 push(mask_scratch); | 4383 push(mask_scratch); |
4376 // shl. May overflow making the check conservative. | 4384 // shl. May overflow making the check conservative. |
4377 addq(mask_scratch, mask_scratch); | 4385 addq(mask_scratch, mask_scratch); |
4378 testq(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); | 4386 testq(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); |
4379 j(zero, &ok, Label::kNear); | 4387 j(zero, &ok, Label::kNear); |
4380 int3(); | 4388 int3(); |
4381 bind(&ok); | 4389 bind(&ok); |
4382 pop(mask_scratch); | 4390 pop(mask_scratch); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4488 bind(&check_prototype); | 4496 bind(&check_prototype); |
4489 movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); | 4497 movq(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); |
4490 cmpq(rcx, null_value); | 4498 cmpq(rcx, null_value); |
4491 j(not_equal, &next); | 4499 j(not_equal, &next); |
4492 } | 4500 } |
4493 | 4501 |
4494 | 4502 |
4495 } } // namespace v8::internal | 4503 } } // namespace v8::internal |
4496 | 4504 |
4497 #endif // V8_TARGET_ARCH_X64 | 4505 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |