1 // Copyright 2014 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 #include "src/ppc/codegen-ppc.h" 6 7 #if V8_TARGET_ARCH_PPC 8 9 #include <memory> 10 11 #include "src/codegen.h" 12 #include "src/macro-assembler.h" 13 #include "src/ppc/simulator-ppc.h" 14 15 namespace v8 { 16 namespace internal { 17 18 19 #define __ masm. 20 21 UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) { 22 #if defined(USE_SIMULATOR) 23 return nullptr; 24 #else 25 size_t actual_size; 26 byte* buffer = 27 static_cast<byte*>(base::OS::Allocate(1 * KB, &actual_size, true)); 28 if (buffer == nullptr) return nullptr; 29 30 MacroAssembler masm(isolate, buffer, static_cast<int>(actual_size), 31 CodeObjectRequired::kNo); 32 33 // Called from C 34 __ function_descriptor(); 35 36 __ MovFromFloatParameter(d1); 37 __ fsqrt(d1, d1); 38 __ MovToFloatResult(d1); 39 __ Ret(); 40 41 CodeDesc desc; 42 masm.GetCode(&desc); 43 DCHECK(ABI_USES_FUNCTION_DESCRIPTORS || !RelocInfo::RequiresRelocation(desc)); 44 45 Assembler::FlushICache(isolate, buffer, actual_size); 46 base::OS::ProtectCode(buffer, actual_size); 47 return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); 48 #endif 49 } 50 51 #undef __ 52 53 54 // ------------------------------------------------------------------------- 55 // Platform-specific RuntimeCallHelper functions. 56 57 void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { 58 masm->EnterFrame(StackFrame::INTERNAL); 59 DCHECK(!masm->has_frame()); 60 masm->set_has_frame(true); 61 } 62 63 64 void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { 65 masm->LeaveFrame(StackFrame::INTERNAL); 66 DCHECK(masm->has_frame()); 67 masm->set_has_frame(false); 68 } 69 70 71 // ------------------------------------------------------------------------- 72 // Code generators 73 74 #define __ ACCESS_MASM(masm) 75 76 // assume ip can be used as a scratch register below 77 void StringCharLoadGenerator::Generate(MacroAssembler* masm, Register string, 78 Register index, Register result, 79 Label* call_runtime) { 80 Label indirect_string_loaded; 81 __ bind(&indirect_string_loaded); 82 83 // Fetch the instance type of the receiver into result register. 84 __ LoadP(result, FieldMemOperand(string, HeapObject::kMapOffset)); 85 __ lbz(result, FieldMemOperand(result, Map::kInstanceTypeOffset)); 86 87 // We need special handling for indirect strings. 88 Label check_sequential; 89 __ andi(r0, result, Operand(kIsIndirectStringMask)); 90 __ beq(&check_sequential, cr0); 91 92 // Dispatch on the indirect string shape: slice or cons or thin. 93 Label cons_string, thin_string; 94 __ andi(ip, result, Operand(kStringRepresentationMask)); 95 __ cmpi(ip, Operand(kConsStringTag)); 96 __ beq(&cons_string); 97 __ cmpi(ip, Operand(kThinStringTag)); 98 __ beq(&thin_string); 99 100 // Handle slices. 101 __ LoadP(result, FieldMemOperand(string, SlicedString::kOffsetOffset)); 102 __ LoadP(string, FieldMemOperand(string, SlicedString::kParentOffset)); 103 __ SmiUntag(ip, result); 104 __ add(index, index, ip); 105 __ b(&indirect_string_loaded); 106 107 // Handle thin strings. 108 __ bind(&thin_string); 109 __ LoadP(string, FieldMemOperand(string, ThinString::kActualOffset)); 110 __ b(&indirect_string_loaded); 111 112 // Handle cons strings. 113 // Check whether the right hand side is the empty string (i.e. if 114 // this is really a flat string in a cons string). If that is not 115 // the case we would rather go to the runtime system now to flatten 116 // the string. 117 __ bind(&cons_string); 118 __ LoadP(result, FieldMemOperand(string, ConsString::kSecondOffset)); 119 __ CompareRoot(result, Heap::kempty_stringRootIndex); 120 __ bne(call_runtime); 121 // Get the first of the two strings and load its instance type. 122 __ LoadP(string, FieldMemOperand(string, ConsString::kFirstOffset)); 123 __ b(&indirect_string_loaded); 124 125 // Distinguish sequential and external strings. Only these two string 126 // representations can reach here (slices and flat cons strings have been 127 // reduced to the underlying sequential or external string). 128 Label external_string, check_encoding; 129 __ bind(&check_sequential); 130 STATIC_ASSERT(kSeqStringTag == 0); 131 __ andi(r0, result, Operand(kStringRepresentationMask)); 132 __ bne(&external_string, cr0); 133 134 // Prepare sequential strings 135 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize); 136 __ addi(string, string, 137 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 138 __ b(&check_encoding); 139 140 // Handle external strings. 141 __ bind(&external_string); 142 if (FLAG_debug_code) { 143 // Assert that we do not have a cons or slice (indirect strings) here. 144 // Sequential strings have already been ruled out. 145 __ andi(r0, result, Operand(kIsIndirectStringMask)); 146 __ Assert(eq, kExternalStringExpectedButNotFound, cr0); 147 } 148 // Rule out short external strings. 149 STATIC_ASSERT(kShortExternalStringTag != 0); 150 __ andi(r0, result, Operand(kShortExternalStringMask)); 151 __ bne(call_runtime, cr0); 152 __ LoadP(string, 153 FieldMemOperand(string, ExternalString::kResourceDataOffset)); 154 155 Label one_byte, done; 156 __ bind(&check_encoding); 157 STATIC_ASSERT(kTwoByteStringTag == 0); 158 __ andi(r0, result, Operand(kStringEncodingMask)); 159 __ bne(&one_byte, cr0); 160 // Two-byte string. 161 __ ShiftLeftImm(result, index, Operand(1)); 162 __ lhzx(result, MemOperand(string, result)); 163 __ b(&done); 164 __ bind(&one_byte); 165 // One-byte string. 166 __ lbzx(result, MemOperand(string, index)); 167 __ bind(&done); 168 } 169 170 #undef __ 171 172 CodeAgingHelper::CodeAgingHelper(Isolate* isolate) { 173 USE(isolate); 174 DCHECK(young_sequence_.length() == kNoCodeAgeSequenceLength); 175 // Since patcher is a large object, allocate it dynamically when needed, 176 // to avoid overloading the stack in stress conditions. 177 // DONT_FLUSH is used because the CodeAgingHelper is initialized early in 178 // the process, before ARM simulator ICache is setup. 179 std::unique_ptr<CodePatcher> patcher( 180 new CodePatcher(isolate, young_sequence_.start(), 181 young_sequence_.length() / Assembler::kInstrSize, 182 CodePatcher::DONT_FLUSH)); 183 PredictableCodeSizeScope scope(patcher->masm(), young_sequence_.length()); 184 patcher->masm()->PushStandardFrame(r4); 185 for (int i = 0; i < kNoCodeAgeSequenceNops; i++) { 186 patcher->masm()->nop(); 187 } 188 } 189 190 191 #ifdef DEBUG 192 bool CodeAgingHelper::IsOld(byte* candidate) const { 193 return Assembler::IsNop(Assembler::instr_at(candidate)); 194 } 195 #endif 196 197 198 bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) { 199 bool result = isolate->code_aging_helper()->IsYoung(sequence); 200 DCHECK(result || isolate->code_aging_helper()->IsOld(sequence)); 201 return result; 202 } 203 204 Code::Age Code::GetCodeAge(Isolate* isolate, byte* sequence) { 205 if (IsYoungSequence(isolate, sequence)) return kNoAgeCodeAge; 206 207 Code* code = NULL; 208 Address target_address = 209 Assembler::target_address_at(sequence + kCodeAgingTargetDelta, code); 210 Code* stub = GetCodeFromTargetAddress(target_address); 211 return GetAgeOfCodeAgeStub(stub); 212 } 213 214 void Code::PatchPlatformCodeAge(Isolate* isolate, byte* sequence, 215 Code::Age age) { 216 uint32_t young_length = isolate->code_aging_helper()->young_sequence_length(); 217 if (age == kNoAgeCodeAge) { 218 isolate->code_aging_helper()->CopyYoungSequenceTo(sequence); 219 Assembler::FlushICache(isolate, sequence, young_length); 220 } else { 221 // FIXED_SEQUENCE 222 Code* stub = GetCodeAgeStub(isolate, age); 223 CodePatcher patcher(isolate, sequence, 224 young_length / Assembler::kInstrSize); 225 Assembler::BlockTrampolinePoolScope block_trampoline_pool(patcher.masm()); 226 intptr_t target = reinterpret_cast<intptr_t>(stub->instruction_start()); 227 // Don't use Call -- we need to preserve ip and lr. 228 // GenerateMakeCodeYoungAgainCommon for the stub code. 229 patcher.masm()->nop(); // marker to detect sequence (see IsOld) 230 patcher.masm()->mov(r3, Operand(target)); 231 patcher.masm()->Jump(r3); 232 for (int i = 0; i < kCodeAgingSequenceNops; i++) { 233 patcher.masm()->nop(); 234 } 235 } 236 } 237 } // namespace internal 238 } // namespace v8 239 240 #endif // V8_TARGET_ARCH_PPC 241