OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_MIPS | 7 #if V8_TARGET_ARCH_MIPS |
8 | 8 |
9 #include "codegen.h" | 9 #include "codegen.h" |
10 #include "macro-assembler.h" | 10 #include "macro-assembler.h" |
(...skipping 1104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 __ ldc1(result, ExpConstant(2, temp3)); | 1115 __ ldc1(result, ExpConstant(2, temp3)); |
1116 | 1116 |
1117 __ bind(&done); | 1117 __ bind(&done); |
1118 } | 1118 } |
1119 | 1119 |
1120 #ifdef DEBUG | 1120 #ifdef DEBUG |
1121 // nop(CODE_AGE_MARKER_NOP) | 1121 // nop(CODE_AGE_MARKER_NOP) |
1122 static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180; | 1122 static const uint32_t kCodeAgePatchFirstInstruction = 0x00010180; |
1123 #endif | 1123 #endif |
1124 | 1124 |
1125 static byte* GetNoCodeAgeSequence(uint32_t* length) { | 1125 |
1126 // The sequence of instructions that is patched out for aging code is the | 1126 CodeAgingHelper::CodeAgingHelper() { |
1127 // following boilerplate stack-building prologue that is found in FUNCTIONS | 1127 ASSERT(young_sequence_.length() == kNoCodeAgeSequenceLength); |
1128 static bool initialized = false; | 1128 // Since patcher is a large object, allocate it dynamically when needed, |
1129 static uint32_t sequence[kNoCodeAgeSequenceLength]; | 1129 // to avoid overloading the stack in stress conditions. |
1130 byte* byte_sequence = reinterpret_cast<byte*>(sequence); | 1130 // DONT_FLUSH is used because the CodeAgingHelper is initialized early in |
1131 *length = kNoCodeAgeSequenceLength * Assembler::kInstrSize; | 1131 // the process, before MIPS simulator ICache is setup. |
1132 if (!initialized) { | 1132 SmartPointer<CodePatcher> patcher( |
1133 // Since patcher is a large object, allocate it dynamically when needed, | 1133 new CodePatcher(young_sequence_.start(), |
1134 // to avoid overloading the stack in stress conditions. | 1134 young_sequence_.length() / Assembler::kInstrSize, |
1135 SmartPointer<CodePatcher> | 1135 CodePatcher::DONT_FLUSH)); |
1136 patcher(new CodePatcher(byte_sequence, kNoCodeAgeSequenceLength)); | 1136 PredictableCodeSizeScope scope(patcher->masm(), young_sequence_.length()); |
1137 PredictableCodeSizeScope scope(patcher->masm(), *length); | 1137 patcher->masm()->Push(ra, fp, cp, a1); |
1138 patcher->masm()->Push(ra, fp, cp, a1); | 1138 patcher->masm()->nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
1139 patcher->masm()->nop(Assembler::CODE_AGE_SEQUENCE_NOP); | 1139 patcher->masm()->Addu( |
1140 patcher->masm()->Addu( | 1140 fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); |
1141 fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | |
1142 initialized = true; | |
1143 } | |
1144 return byte_sequence; | |
1145 } | 1141 } |
1146 | 1142 |
1147 | 1143 |
1148 bool Code::IsYoungSequence(byte* sequence) { | 1144 #ifdef DEBUG |
1149 uint32_t young_length; | 1145 bool CodeAgingHelper::IsOld(byte* candidate) const { |
1150 byte* young_sequence = GetNoCodeAgeSequence(&young_length); | 1146 return Memory::uint32_at(candidate) == kCodeAgePatchFirstInstruction; |
1151 bool result = !memcmp(sequence, young_sequence, young_length); | 1147 } |
1152 ASSERT(result || | 1148 #endif |
1153 Memory::uint32_at(sequence) == kCodeAgePatchFirstInstruction); | 1149 |
| 1150 |
| 1151 bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) { |
| 1152 bool result = isolate->code_aging_helper()->IsYoung(sequence); |
| 1153 ASSERT(result || isolate->code_aging_helper()->IsOld(sequence)); |
1154 return result; | 1154 return result; |
1155 } | 1155 } |
1156 | 1156 |
1157 | 1157 |
1158 void Code::GetCodeAgeAndParity(byte* sequence, Age* age, | 1158 void Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age, |
1159 MarkingParity* parity) { | 1159 MarkingParity* parity) { |
1160 if (IsYoungSequence(sequence)) { | 1160 if (IsYoungSequence(isolate, sequence)) { |
1161 *age = kNoAgeCodeAge; | 1161 *age = kNoAgeCodeAge; |
1162 *parity = NO_MARKING_PARITY; | 1162 *parity = NO_MARKING_PARITY; |
1163 } else { | 1163 } else { |
1164 Address target_address = Assembler::target_address_at( | 1164 Address target_address = Assembler::target_address_at( |
1165 sequence + Assembler::kInstrSize); | 1165 sequence + Assembler::kInstrSize); |
1166 Code* stub = GetCodeFromTargetAddress(target_address); | 1166 Code* stub = GetCodeFromTargetAddress(target_address); |
1167 GetCodeAgeAndParity(stub, age, parity); | 1167 GetCodeAgeAndParity(stub, age, parity); |
1168 } | 1168 } |
1169 } | 1169 } |
1170 | 1170 |
1171 | 1171 |
1172 void Code::PatchPlatformCodeAge(Isolate* isolate, | 1172 void Code::PatchPlatformCodeAge(Isolate* isolate, |
1173 byte* sequence, | 1173 byte* sequence, |
1174 Code::Age age, | 1174 Code::Age age, |
1175 MarkingParity parity) { | 1175 MarkingParity parity) { |
1176 uint32_t young_length; | 1176 uint32_t young_length = isolate->code_aging_helper()->young_sequence_length(); |
1177 byte* young_sequence = GetNoCodeAgeSequence(&young_length); | |
1178 if (age == kNoAgeCodeAge) { | 1177 if (age == kNoAgeCodeAge) { |
1179 CopyBytes(sequence, young_sequence, young_length); | 1178 isolate->code_aging_helper()->CopyYoungSequenceTo(sequence); |
1180 CPU::FlushICache(sequence, young_length); | 1179 CPU::FlushICache(sequence, young_length); |
1181 } else { | 1180 } else { |
1182 Code* stub = GetCodeAgeStub(isolate, age, parity); | 1181 Code* stub = GetCodeAgeStub(isolate, age, parity); |
1183 CodePatcher patcher(sequence, young_length / Assembler::kInstrSize); | 1182 CodePatcher patcher(sequence, young_length / Assembler::kInstrSize); |
1184 // Mark this code sequence for FindPlatformCodeAgeSequence(). | 1183 // Mark this code sequence for FindPlatformCodeAgeSequence(). |
1185 patcher.masm()->nop(Assembler::CODE_AGE_MARKER_NOP); | 1184 patcher.masm()->nop(Assembler::CODE_AGE_MARKER_NOP); |
1186 // Load the stub address to t9 and call it, | 1185 // Load the stub address to t9 and call it, |
1187 // GetCodeAgeAndParity() extracts the stub address from this instruction. | 1186 // GetCodeAgeAndParity() extracts the stub address from this instruction. |
1188 patcher.masm()->li( | 1187 patcher.masm()->li( |
1189 t9, | 1188 t9, |
1190 Operand(reinterpret_cast<uint32_t>(stub->instruction_start())), | 1189 Operand(reinterpret_cast<uint32_t>(stub->instruction_start())), |
1191 CONSTANT_SIZE); | 1190 CONSTANT_SIZE); |
1192 patcher.masm()->nop(); // Prevent jalr to jal optimization. | 1191 patcher.masm()->nop(); // Prevent jalr to jal optimization. |
1193 patcher.masm()->jalr(t9, a0); | 1192 patcher.masm()->jalr(t9, a0); |
1194 patcher.masm()->nop(); // Branch delay slot nop. | 1193 patcher.masm()->nop(); // Branch delay slot nop. |
1195 patcher.masm()->nop(); // Pad the empty space. | 1194 patcher.masm()->nop(); // Pad the empty space. |
1196 } | 1195 } |
1197 } | 1196 } |
1198 | 1197 |
1199 | 1198 |
1200 #undef __ | 1199 #undef __ |
1201 | 1200 |
1202 } } // namespace v8::internal | 1201 } } // namespace v8::internal |
1203 | 1202 |
1204 #endif // V8_TARGET_ARCH_MIPS | 1203 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |