1 // Copyright 2015 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_S390 6 7 #include "src/ic/ic.h" 8 #include "src/codegen.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 kNoCondition; 31 } 32 } 33 34 bool CompareIC::HasInlinedSmiCode(Address address) { 35 // The address of the instruction following the call. 36 Address cmp_instruction_address = 37 Assembler::return_address_from_call_start(address); 38 39 // If the instruction following the call is not a CHI, nothing 40 // was inlined. 41 return (Instruction::S390OpcodeValue(cmp_instruction_address) == CHI); 42 } 43 44 // 45 // This code is paired with the JumpPatchSite class in full-codegen-s390.cc 46 // 47 void PatchInlinedSmiCode(Isolate* isolate, Address address, 48 InlinedSmiCheck check) { 49 Address cmp_instruction_address = 50 Assembler::return_address_from_call_start(address); 51 52 // If the instruction following the call is not a cmp rx, #yyy, nothing 53 // was inlined. 54 Instr instr = Assembler::instr_at(cmp_instruction_address); 55 if (Instruction::S390OpcodeValue(cmp_instruction_address) != CHI) { 56 return; 57 } 58 59 if (Instruction::S390OpcodeValue(address) != BRASL) { 60 return; 61 } 62 // The delta to the start of the map check instruction and the 63 // condition code uses at the patched jump. 64 int delta = instr & 0x0000ffff; 65 66 // If the delta is 0 the instruction is cmp r0, #0 which also signals that 67 // nothing was inlined. 68 if (delta == 0) { 69 return; 70 } 71 72 if (FLAG_trace_ic) { 73 LOG(isolate, PatchIC(address, cmp_instruction_address, delta)); 74 } 75 76 // Expected sequence to enable by changing the following 77 // CR/CGR Rx, Rx // 2 / 4 bytes 78 // LR R0, R0 // 2 bytes // 31-bit only! 79 // BRC/BRCL // 4 / 6 bytes 80 // into 81 // TMLL Rx, XXX // 4 bytes 82 // BRC/BRCL // 4 / 6 bytes 83 // And vice versa to disable. 84 85 // The following constant is the size of the CR/CGR + LR + LR 86 const int kPatchAreaSizeNoBranch = 4; 87 Address patch_address = cmp_instruction_address - delta; 88 Address branch_address = patch_address + kPatchAreaSizeNoBranch; 89 90 Instr instr_at_patch = Assembler::instr_at(patch_address); 91 SixByteInstr branch_instr = Assembler::instr_at(branch_address); 92 93 // This is patching a conditional "jump if not smi/jump if smi" site. 94 size_t patch_size = 0; 95 if (Instruction::S390OpcodeValue(branch_address) == BRC) { 96 patch_size = kPatchAreaSizeNoBranch + 4; 97 } else if (Instruction::S390OpcodeValue(branch_address) == BRCL) { 98 patch_size = kPatchAreaSizeNoBranch + 6; 99 } else { 100 DCHECK(false); 101 } 102 CodePatcher patcher(isolate, patch_address, patch_size); 103 Register reg; 104 reg.reg_code = instr_at_patch & 0xf; 105 if (check == ENABLE_INLINED_SMI_CHECK) { 106 patcher.masm()->TestIfSmi(reg); 107 } else { 108 // Emit the NOP to ensure sufficient place for patching 109 // (replaced by LR + NILL) 110 DCHECK(check == DISABLE_INLINED_SMI_CHECK); 111 patcher.masm()->CmpP(reg, reg); 112 #ifndef V8_TARGET_ARCH_S390X 113 patcher.masm()->nop(); 114 #endif 115 } 116 117 Condition cc = al; 118 if (Instruction::S390OpcodeValue(branch_address) == BRC) { 119 cc = static_cast<Condition>((branch_instr & 0x00f00000) >> 20); 120 DCHECK((cc == ne) || (cc == eq)); 121 cc = (cc == ne) ? eq : ne; 122 patcher.masm()->brc(cc, Operand(branch_instr & 0xffff)); 123 } else if (Instruction::S390OpcodeValue(branch_address) == BRCL) { 124 cc = static_cast<Condition>( 125 (branch_instr & (static_cast<uint64_t>(0x00f0) << 32)) >> 36); 126 DCHECK((cc == ne) || (cc == eq)); 127 cc = (cc == ne) ? eq : ne; 128 patcher.masm()->brcl(cc, Operand(branch_instr & 0xffffffff)); 129 } else { 130 DCHECK(false); 131 } 132 } 133 134 } // namespace internal 135 } // namespace v8 136 137 #endif // V8_TARGET_ARCH_S390 138