Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(843)

Side by Side Diff: src/compiler/code-generator.cc

Issue 504493002: Fix deoptimization address patching in Turbofan to use safepoints. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Compilation fix. Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/compiler/code-generator.h ('k') | src/compiler/instruction-selector.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/code-generator.h ('k') | src/compiler/instruction-selector.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698