| // Copyright 2012 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #if V8_TARGET_ARCH_X64 |
| |
| #include "src/codegen.h" |
| #include "src/ic/ic.h" |
| #include "src/ic/stub-cache.h" |
| #include "src/objects-inl.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| |
| Condition CompareIC::ComputeCondition(Token::Value op) { |
| switch (op) { |
| case Token::EQ_STRICT: |
| case Token::EQ: |
| return equal; |
| case Token::LT: |
| return less; |
| case Token::GT: |
| return greater; |
| case Token::LTE: |
| return less_equal; |
| case Token::GTE: |
| return greater_equal; |
| default: |
| UNREACHABLE(); |
| return no_condition; |
| } |
| } |
| |
| |
| bool CompareIC::HasInlinedSmiCode(Address address) { |
| // The address of the instruction following the call. |
| Address test_instruction_address = |
| address + Assembler::kCallTargetAddressOffset; |
| |
| // If the instruction following the call is not a test al, nothing |
| // was inlined. |
| return *test_instruction_address == Assembler::kTestAlByte; |
| } |
| |
| |
| void PatchInlinedSmiCode(Isolate* isolate, Address address, |
| InlinedSmiCheck check) { |
| // The address of the instruction following the call. |
| Address test_instruction_address = |
| address + Assembler::kCallTargetAddressOffset; |
| |
| // If the instruction following the call is not a test al, nothing |
| // was inlined. |
| if (*test_instruction_address != Assembler::kTestAlByte) { |
| DCHECK(*test_instruction_address == Assembler::kNopByte); |
| return; |
| } |
| |
| Address delta_address = test_instruction_address + 1; |
| // The delta to the start of the map check instruction and the |
| // condition code uses at the patched jump. |
| uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address); |
| if (FLAG_trace_ic) { |
| LOG(isolate, PatchIC(address, test_instruction_address, delta)); |
| } |
| |
| // Patch with a short conditional jump. Enabling means switching from a short |
| // jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the |
| // reverse operation of that. |
| Address jmp_address = test_instruction_address - delta; |
| DCHECK((check == ENABLE_INLINED_SMI_CHECK) |
| ? (*jmp_address == Assembler::kJncShortOpcode || |
| *jmp_address == Assembler::kJcShortOpcode) |
| : (*jmp_address == Assembler::kJnzShortOpcode || |
| *jmp_address == Assembler::kJzShortOpcode)); |
| Condition cc = |
| (check == ENABLE_INLINED_SMI_CHECK) |
| ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
| : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
| *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| } |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_TARGET_ARCH_X64 |