| 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 |