OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 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 | 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 "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
8 #include "src/compiler/linkage.h" | 8 #include "src/compiler/linkage.h" |
9 #include "src/compiler/pipeline.h" | 9 #include "src/compiler/pipeline.h" |
10 | 10 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 AssemblePrologue(); | 46 AssemblePrologue(); |
47 | 47 |
48 // Assemble all instructions. | 48 // Assemble all instructions. |
49 for (InstructionSequence::const_iterator i = code()->begin(); | 49 for (InstructionSequence::const_iterator i = code()->begin(); |
50 i != code()->end(); ++i) { | 50 i != code()->end(); ++i) { |
51 AssembleInstruction(*i); | 51 AssembleInstruction(*i); |
52 } | 52 } |
53 | 53 |
54 FinishCode(masm()); | 54 FinishCode(masm()); |
55 | 55 |
| 56 UpdateSafepointsWithDeoptimizationPc(); |
56 safepoints()->Emit(masm(), frame()->GetSpillSlotCount()); | 57 safepoints()->Emit(masm(), frame()->GetSpillSlotCount()); |
57 | 58 |
58 // TODO(titzer): what are the right code flags here? | 59 // TODO(titzer): what are the right code flags here? |
59 Code::Kind kind = Code::STUB; | 60 Code::Kind kind = Code::STUB; |
60 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) { | 61 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) { |
61 kind = Code::OPTIMIZED_FUNCTION; | 62 kind = Code::OPTIMIZED_FUNCTION; |
62 } | 63 } |
63 Handle<Code> result = v8::internal::CodeGenerator::MakeCodeEpilogue( | 64 Handle<Code> result = v8::internal::CodeGenerator::MakeCodeEpilogue( |
64 masm(), Code::ComputeFlags(kind), info); | 65 masm(), Code::ComputeFlags(kind), info); |
65 result->set_is_turbofanned(true); | 66 result->set_is_turbofanned(true); |
66 result->set_stack_slots(frame()->GetSpillSlotCount()); | 67 result->set_stack_slots(frame()->GetSpillSlotCount()); |
67 result->set_safepoint_table_offset(safepoints()->GetCodeOffset()); | 68 result->set_safepoint_table_offset(safepoints()->GetCodeOffset()); |
68 | 69 |
69 PopulateDeoptimizationData(result); | 70 PopulateDeoptimizationData(result); |
70 | 71 |
71 // Emit a code line info recording stop event. | 72 // Emit a code line info recording stop event. |
72 void* line_info = recorder->DetachJITHandlerData(); | 73 void* line_info = recorder->DetachJITHandlerData(); |
73 LOG_CODE_EVENT(isolate(), CodeEndLinePosInfoRecordEvent(*result, line_info)); | 74 LOG_CODE_EVENT(isolate(), CodeEndLinePosInfoRecordEvent(*result, line_info)); |
74 | 75 |
75 return result; | 76 return result; |
76 } | 77 } |
77 | 78 |
78 | 79 |
79 void CodeGenerator::RecordSafepoint(PointerMap* pointers, Safepoint::Kind kind, | 80 Safepoint::Id CodeGenerator::RecordSafepoint(PointerMap* pointers, |
80 int arguments, | 81 Safepoint::Kind kind, |
81 Safepoint::DeoptMode deopt_mode) { | 82 int arguments, |
| 83 Safepoint::DeoptMode deopt_mode) { |
82 const ZoneList<InstructionOperand*>* operands = | 84 const ZoneList<InstructionOperand*>* operands = |
83 pointers->GetNormalizedOperands(); | 85 pointers->GetNormalizedOperands(); |
84 Safepoint safepoint = | 86 Safepoint safepoint = |
85 safepoints()->DefineSafepoint(masm(), kind, arguments, deopt_mode); | 87 safepoints()->DefineSafepoint(masm(), kind, arguments, deopt_mode); |
86 for (int i = 0; i < operands->length(); i++) { | 88 for (int i = 0; i < operands->length(); i++) { |
87 InstructionOperand* pointer = operands->at(i); | 89 InstructionOperand* pointer = operands->at(i); |
88 if (pointer->IsStackSlot()) { | 90 if (pointer->IsStackSlot()) { |
89 safepoint.DefinePointerSlot(pointer->index(), zone()); | 91 safepoint.DefinePointerSlot(pointer->index(), zone()); |
90 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 92 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
91 Register reg = Register::FromAllocationIndex(pointer->index()); | 93 Register reg = Register::FromAllocationIndex(pointer->index()); |
92 safepoint.DefinePointerRegister(reg, zone()); | 94 safepoint.DefinePointerRegister(reg, zone()); |
93 } | 95 } |
94 } | 96 } |
| 97 return safepoint.id(); |
95 } | 98 } |
96 | 99 |
97 | 100 |
98 void CodeGenerator::AssembleInstruction(Instruction* instr) { | 101 void CodeGenerator::AssembleInstruction(Instruction* instr) { |
99 if (instr->IsBlockStart()) { | 102 if (instr->IsBlockStart()) { |
100 // Bind a label for a block start and handle parallel moves. | 103 // Bind a label for a block start and handle parallel moves. |
101 BlockStartInstruction* block_start = BlockStartInstruction::cast(instr); | 104 BlockStartInstruction* block_start = BlockStartInstruction::cast(instr); |
102 current_block_ = block_start->block(); | 105 current_block_ = block_start->block(); |
103 if (FLAG_code_comments) { | 106 if (FLAG_code_comments) { |
104 // TODO(titzer): these code comments are a giant memory leak. | 107 // TODO(titzer): these code comments are a giant memory leak. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 for (int i = GapInstruction::FIRST_INNER_POSITION; | 168 for (int i = GapInstruction::FIRST_INNER_POSITION; |
166 i <= GapInstruction::LAST_INNER_POSITION; i++) { | 169 i <= GapInstruction::LAST_INNER_POSITION; i++) { |
167 GapInstruction::InnerPosition inner_pos = | 170 GapInstruction::InnerPosition inner_pos = |
168 static_cast<GapInstruction::InnerPosition>(i); | 171 static_cast<GapInstruction::InnerPosition>(i); |
169 ParallelMove* move = instr->GetParallelMove(inner_pos); | 172 ParallelMove* move = instr->GetParallelMove(inner_pos); |
170 if (move != NULL) resolver()->Resolve(move); | 173 if (move != NULL) resolver()->Resolve(move); |
171 } | 174 } |
172 } | 175 } |
173 | 176 |
174 | 177 |
| 178 void CodeGenerator::UpdateSafepointsWithDeoptimizationPc() { |
| 179 int patch_count = static_cast<int>(lazy_deoptimization_entries_.size()); |
| 180 for (int i = 0; i < patch_count; ++i) { |
| 181 LazyDeoptimizationEntry entry = lazy_deoptimization_entries_[i]; |
| 182 // TODO(jarin) make sure that there is no code (other than nops) |
| 183 // between the call position and the continuation position. |
| 184 safepoints()->SetDeoptimizationPc(entry.safepoint_id(), |
| 185 entry.deoptimization()->pos()); |
| 186 } |
| 187 } |
| 188 |
| 189 |
175 void CodeGenerator::PopulateDeoptimizationData(Handle<Code> code_object) { | 190 void CodeGenerator::PopulateDeoptimizationData(Handle<Code> code_object) { |
176 CompilationInfo* info = linkage()->info(); | 191 CompilationInfo* info = linkage()->info(); |
177 int deopt_count = code()->GetDeoptimizationEntryCount(); | 192 int deopt_count = code()->GetDeoptimizationEntryCount(); |
178 int patch_count = static_cast<int>(lazy_deoptimization_entries_.size()); | 193 int patch_count = static_cast<int>(lazy_deoptimization_entries_.size()); |
179 if (patch_count == 0 && deopt_count == 0) return; | 194 if (patch_count == 0 && deopt_count == 0) return; |
180 Handle<DeoptimizationInputData> data = DeoptimizationInputData::New( | 195 Handle<DeoptimizationInputData> data = |
181 isolate(), deopt_count, patch_count, TENURED); | 196 DeoptimizationInputData::New(isolate(), deopt_count, TENURED); |
182 | 197 |
183 Handle<ByteArray> translation_array = | 198 Handle<ByteArray> translation_array = |
184 translations_.CreateByteArray(isolate()->factory()); | 199 translations_.CreateByteArray(isolate()->factory()); |
185 | 200 |
186 data->SetTranslationByteArray(*translation_array); | 201 data->SetTranslationByteArray(*translation_array); |
187 data->SetInlinedFunctionCount(Smi::FromInt(0)); | 202 data->SetInlinedFunctionCount(Smi::FromInt(0)); |
188 data->SetOptimizationId(Smi::FromInt(info->optimization_id())); | 203 data->SetOptimizationId(Smi::FromInt(info->optimization_id())); |
189 // TODO(jarin) The following code was copied over from Lithium, not sure | 204 // TODO(jarin) The following code was copied over from Lithium, not sure |
190 // whether the scope or the IsOptimizing condition are really needed. | 205 // whether the scope or the IsOptimizing condition are really needed. |
191 if (info->IsOptimizing()) { | 206 if (info->IsOptimizing()) { |
(...skipping 23 matching lines...) Expand all Loading... |
215 for (int i = 0; i < deopt_count; i++) { | 230 for (int i = 0; i < deopt_count; i++) { |
216 FrameStateDescriptor* descriptor = code()->GetDeoptimizationEntry(i); | 231 FrameStateDescriptor* descriptor = code()->GetDeoptimizationEntry(i); |
217 data->SetAstId(i, descriptor->bailout_id()); | 232 data->SetAstId(i, descriptor->bailout_id()); |
218 CHECK_NE(NULL, deoptimization_states_[i]); | 233 CHECK_NE(NULL, deoptimization_states_[i]); |
219 data->SetTranslationIndex( | 234 data->SetTranslationIndex( |
220 i, Smi::FromInt(deoptimization_states_[i]->translation_id_)); | 235 i, Smi::FromInt(deoptimization_states_[i]->translation_id_)); |
221 data->SetArgumentsStackHeight(i, Smi::FromInt(0)); | 236 data->SetArgumentsStackHeight(i, Smi::FromInt(0)); |
222 data->SetPc(i, Smi::FromInt(-1)); | 237 data->SetPc(i, Smi::FromInt(-1)); |
223 } | 238 } |
224 | 239 |
225 // Populate the return address patcher entries. | |
226 for (int i = 0; i < patch_count; ++i) { | |
227 LazyDeoptimizationEntry entry = lazy_deoptimization_entries_[i]; | |
228 data->SetReturnAddressPc(i, Smi::FromInt(entry.position_after_call())); | |
229 data->SetPatchedAddressPc(i, Smi::FromInt(entry.deoptimization()->pos())); | |
230 } | |
231 | |
232 code_object->set_deoptimization_data(*data); | 240 code_object->set_deoptimization_data(*data); |
233 } | 241 } |
234 | 242 |
235 | 243 |
236 void CodeGenerator::AddSafepointAndDeopt(Instruction* instr) { | 244 void CodeGenerator::AddSafepointAndDeopt(Instruction* instr) { |
237 CallDescriptor::DeoptimizationSupport deopt = | 245 CallDescriptor::DeoptimizationSupport deopt = |
238 static_cast<CallDescriptor::DeoptimizationSupport>( | 246 static_cast<CallDescriptor::DeoptimizationSupport>( |
239 MiscField::decode(instr->opcode())); | 247 MiscField::decode(instr->opcode())); |
240 | 248 |
241 if ((deopt & CallDescriptor::kLazyDeoptimization) != 0) { | |
242 RecordLazyDeoptimizationEntry(instr); | |
243 } | |
244 | |
245 bool needs_frame_state = (deopt & CallDescriptor::kNeedsFrameState) != 0; | 249 bool needs_frame_state = (deopt & CallDescriptor::kNeedsFrameState) != 0; |
246 | 250 |
247 RecordSafepoint( | 251 Safepoint::Id safepoint_id = RecordSafepoint( |
248 instr->pointer_map(), Safepoint::kSimple, 0, | 252 instr->pointer_map(), Safepoint::kSimple, 0, |
249 needs_frame_state ? Safepoint::kLazyDeopt : Safepoint::kNoLazyDeopt); | 253 needs_frame_state ? Safepoint::kLazyDeopt : Safepoint::kNoLazyDeopt); |
250 | 254 |
251 if ((deopt & CallDescriptor::kNeedsFrameState) != 0) { | 255 if ((deopt & CallDescriptor::kLazyDeoptimization) != 0) { |
| 256 RecordLazyDeoptimizationEntry(instr, safepoint_id); |
| 257 } |
| 258 |
| 259 if (needs_frame_state) { |
252 // If the frame state is present, it starts at argument 1 | 260 // If the frame state is present, it starts at argument 1 |
253 // (just after the code address). | 261 // (just after the code address). |
254 InstructionOperandConverter converter(this, instr); | 262 InstructionOperandConverter converter(this, instr); |
255 // Argument 1 is deoptimization id. | 263 // Argument 1 is deoptimization id. |
256 int deoptimization_id = converter.ToConstant(instr->InputAt(1)).ToInt32(); | 264 int deoptimization_id = converter.ToConstant(instr->InputAt(1)).ToInt32(); |
257 // The actual frame state values start with argument 2. | 265 // The actual frame state values start with argument 2. |
258 BuildTranslation(instr, 2, deoptimization_id); | 266 int first_state_value_offset = 2; |
| 267 #if DEBUG |
| 268 // Make sure all the values live in stack slots or they are immediates. |
| 269 // (The values should not live in register because registers are clobbered |
| 270 // by calls.) |
| 271 FrameStateDescriptor* descriptor = |
| 272 code()->GetDeoptimizationEntry(deoptimization_id); |
| 273 for (int i = 0; i < descriptor->size(); i++) { |
| 274 InstructionOperand* op = instr->InputAt(first_state_value_offset + i); |
| 275 CHECK(op->IsStackSlot() || op->IsImmediate()); |
| 276 } |
| 277 #endif |
| 278 BuildTranslation(instr, first_state_value_offset, deoptimization_id); |
259 safepoints()->RecordLazyDeoptimizationIndex(deoptimization_id); | 279 safepoints()->RecordLazyDeoptimizationIndex(deoptimization_id); |
260 } | 280 } |
261 } | 281 } |
262 | 282 |
263 | 283 |
264 void CodeGenerator::RecordLazyDeoptimizationEntry(Instruction* instr) { | 284 void CodeGenerator::RecordLazyDeoptimizationEntry(Instruction* instr, |
| 285 Safepoint::Id safepoint_id) { |
265 InstructionOperandConverter i(this, instr); | 286 InstructionOperandConverter i(this, instr); |
266 | 287 |
267 Label after_call; | 288 Label after_call; |
268 masm()->bind(&after_call); | 289 masm()->bind(&after_call); |
269 | 290 |
270 // The continuation and deoptimization are the last two inputs: | 291 // The continuation and deoptimization are the last two inputs: |
271 BasicBlock* cont_block = | 292 BasicBlock* cont_block = |
272 i.InputBlock(static_cast<int>(instr->InputCount()) - 2); | 293 i.InputBlock(static_cast<int>(instr->InputCount()) - 2); |
273 BasicBlock* deopt_block = | 294 BasicBlock* deopt_block = |
274 i.InputBlock(static_cast<int>(instr->InputCount()) - 1); | 295 i.InputBlock(static_cast<int>(instr->InputCount()) - 1); |
275 | 296 |
276 Label* cont_label = code_->GetLabel(cont_block); | 297 Label* cont_label = code_->GetLabel(cont_block); |
277 Label* deopt_label = code_->GetLabel(deopt_block); | 298 Label* deopt_label = code_->GetLabel(deopt_block); |
278 | 299 |
279 lazy_deoptimization_entries_.push_back( | 300 lazy_deoptimization_entries_.push_back(LazyDeoptimizationEntry( |
280 LazyDeoptimizationEntry(after_call.pos(), cont_label, deopt_label)); | 301 after_call.pos(), cont_label, deopt_label, safepoint_id)); |
281 } | 302 } |
282 | 303 |
283 | 304 |
284 int CodeGenerator::DefineDeoptimizationLiteral(Handle<Object> literal) { | 305 int CodeGenerator::DefineDeoptimizationLiteral(Handle<Object> literal) { |
285 int result = static_cast<int>(deoptimization_literals_.size()); | 306 int result = static_cast<int>(deoptimization_literals_.size()); |
286 for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) { | 307 for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) { |
287 if (deoptimization_literals_[i].is_identical_to(literal)) return i; | 308 if (deoptimization_literals_[i].is_identical_to(literal)) return i; |
288 } | 309 } |
289 deoptimization_literals_.push_back(literal); | 310 deoptimization_literals_.push_back(literal); |
290 return result; | 311 return result; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 } | 411 } |
391 | 412 |
392 | 413 |
393 void CodeGenerator::AddNopForSmiCodeInlining() { UNIMPLEMENTED(); } | 414 void CodeGenerator::AddNopForSmiCodeInlining() { UNIMPLEMENTED(); } |
394 | 415 |
395 #endif // !V8_TURBOFAN_BACKEND | 416 #endif // !V8_TURBOFAN_BACKEND |
396 | 417 |
397 } // namespace compiler | 418 } // namespace compiler |
398 } // namespace internal | 419 } // namespace internal |
399 } // namespace v8 | 420 } // namespace v8 |
OLD | NEW |