Home | History | Annotate | Download | only in arm64
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #if V8_TARGET_ARCH_ARM64
      6 
      7 #include "src/codegen.h"
      8 #include "src/ic/ic.h"
      9 #include "src/ic/stub-cache.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 
     14 
     15 Condition CompareIC::ComputeCondition(Token::Value op) {
     16   switch (op) {
     17     case Token::EQ_STRICT:
     18     case Token::EQ:
     19       return eq;
     20     case Token::LT:
     21       return lt;
     22     case Token::GT:
     23       return gt;
     24     case Token::LTE:
     25       return le;
     26     case Token::GTE:
     27       return ge;
     28     default:
     29       UNREACHABLE();
     30       return al;
     31   }
     32 }
     33 
     34 
     35 bool CompareIC::HasInlinedSmiCode(Address address) {
     36   // The address of the instruction following the call.
     37   Address info_address = Assembler::return_address_from_call_start(address);
     38 
     39   InstructionSequence* patch_info = InstructionSequence::At(info_address);
     40   return patch_info->IsInlineData();
     41 }
     42 
     43 
     44 // Activate a SMI fast-path by patching the instructions generated by
     45 // JumpPatchSite::EmitJumpIf(Not)Smi(), using the information encoded by
     46 // JumpPatchSite::EmitPatchInfo().
     47 void PatchInlinedSmiCode(Isolate* isolate, Address address,
     48                          InlinedSmiCheck check) {
     49   // The patch information is encoded in the instruction stream using
     50   // instructions which have no side effects, so we can safely execute them.
     51   // The patch information is encoded directly after the call to the helper
     52   // function which is requesting this patch operation.
     53   Address info_address = Assembler::return_address_from_call_start(address);
     54   InlineSmiCheckInfo info(info_address);
     55 
     56   // Check and decode the patch information instruction.
     57   if (!info.HasSmiCheck()) {
     58     return;
     59   }
     60 
     61   if (FLAG_trace_ic) {
     62     LOG(isolate, PatchIC(address, info_address, info.SmiCheckDelta()));
     63   }
     64 
     65   // Patch and activate code generated by JumpPatchSite::EmitJumpIfNotSmi()
     66   // and JumpPatchSite::EmitJumpIfSmi().
     67   // Changing
     68   //   tb(n)z xzr, #0, <target>
     69   // to
     70   //   tb(!n)z test_reg, #0, <target>
     71   Instruction* to_patch = info.SmiCheck();
     72   PatchingAssembler patcher(isolate, to_patch, 1);
     73   DCHECK(to_patch->IsTestBranch());
     74   DCHECK(to_patch->ImmTestBranchBit5() == 0);
     75   DCHECK(to_patch->ImmTestBranchBit40() == 0);
     76 
     77   STATIC_ASSERT(kSmiTag == 0);
     78   STATIC_ASSERT(kSmiTagMask == 1);
     79 
     80   int branch_imm = to_patch->ImmTestBranch();
     81   Register smi_reg;
     82   if (check == ENABLE_INLINED_SMI_CHECK) {
     83     DCHECK(to_patch->Rt() == xzr.code());
     84     smi_reg = info.SmiRegister();
     85   } else {
     86     DCHECK(check == DISABLE_INLINED_SMI_CHECK);
     87     DCHECK(to_patch->Rt() != xzr.code());
     88     smi_reg = xzr;
     89   }
     90 
     91   if (to_patch->Mask(TestBranchMask) == TBZ) {
     92     // This is JumpIfNotSmi(smi_reg, branch_imm).
     93     patcher.tbnz(smi_reg, 0, branch_imm);
     94   } else {
     95     DCHECK(to_patch->Mask(TestBranchMask) == TBNZ);
     96     // This is JumpIfSmi(smi_reg, branch_imm).
     97     patcher.tbz(smi_reg, 0, branch_imm);
     98   }
     99 }
    100 }  // namespace internal
    101 }  // namespace v8
    102 
    103 #endif  // V8_TARGET_ARCH_ARM64
    104