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

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

Issue 522873002: Removal of the deoptimization block from Turbofan (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Change constant capitalization Created 6 years, 3 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/common-operator.h » ('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
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 namespace compiler { 13 namespace compiler {
14 14
15 CodeGenerator::CodeGenerator(InstructionSequence* code) 15 CodeGenerator::CodeGenerator(InstructionSequence* code)
16 : code_(code), 16 : code_(code),
17 current_block_(NULL), 17 current_block_(NULL),
18 current_source_position_(SourcePosition::Invalid()), 18 current_source_position_(SourcePosition::Invalid()),
19 masm_(code->zone()->isolate(), NULL, 0), 19 masm_(code->zone()->isolate(), NULL, 0),
20 resolver_(this), 20 resolver_(this),
21 safepoints_(code->zone()), 21 safepoints_(code->zone()),
22 lazy_deoptimization_entries_(code->zone()), 22 deoptimization_points_(code->zone()),
23 deoptimization_states_(code->zone()), 23 deoptimization_states_(code->zone()),
24 deoptimization_literals_(code->zone()), 24 deoptimization_literals_(code->zone()),
25 translations_(code->zone()) { 25 translations_(code->zone()) {}
26 deoptimization_states_.resize(code->GetDeoptimizationEntryCount(), NULL);
27 }
28 26
29 27
30 Handle<Code> CodeGenerator::GenerateCode() { 28 Handle<Code> CodeGenerator::GenerateCode() {
31 CompilationInfo* info = linkage()->info(); 29 CompilationInfo* info = linkage()->info();
32 30
33 // Emit a code line info recording start event. 31 // Emit a code line info recording start event.
34 PositionsRecorder* recorder = masm()->positions_recorder(); 32 PositionsRecorder* recorder = masm()->positions_recorder();
35 LOG_CODE_EVENT(isolate(), CodeStartLinePosInfoRecordEvent(recorder)); 33 LOG_CODE_EVENT(isolate(), CodeStartLinePosInfoRecordEvent(recorder));
36 34
37 // Place function entry hook if requested to do so. 35 // Place function entry hook if requested to do so.
38 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) { 36 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) {
39 ProfileEntryHookStub::MaybeCallEntryHook(masm()); 37 ProfileEntryHookStub::MaybeCallEntryHook(masm());
40 } 38 }
41 39
42 // Architecture-specific, linkage-specific prologue. 40 // Architecture-specific, linkage-specific prologue.
43 info->set_prologue_offset(masm()->pc_offset()); 41 info->set_prologue_offset(masm()->pc_offset());
44 AssemblePrologue(); 42 AssemblePrologue();
45 43
46 // Assemble all instructions. 44 // Assemble all instructions.
47 for (InstructionSequence::const_iterator i = code()->begin(); 45 for (InstructionSequence::const_iterator i = code()->begin();
48 i != code()->end(); ++i) { 46 i != code()->end(); ++i) {
49 AssembleInstruction(*i); 47 AssembleInstruction(*i);
50 } 48 }
51 49
50 EmitLazyDeoptimizationCallTable();
51
52 FinishCode(masm()); 52 FinishCode(masm());
53 53
54 UpdateSafepointsWithDeoptimizationPc();
55 safepoints()->Emit(masm(), frame()->GetSpillSlotCount()); 54 safepoints()->Emit(masm(), frame()->GetSpillSlotCount());
56 55
57 // TODO(titzer): what are the right code flags here? 56 // TODO(titzer): what are the right code flags here?
58 Code::Kind kind = Code::STUB; 57 Code::Kind kind = Code::STUB;
59 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) { 58 if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) {
60 kind = Code::OPTIMIZED_FUNCTION; 59 kind = Code::OPTIMIZED_FUNCTION;
61 } 60 }
62 Handle<Code> result = v8::internal::CodeGenerator::MakeCodeEpilogue( 61 Handle<Code> result = v8::internal::CodeGenerator::MakeCodeEpilogue(
63 masm(), Code::ComputeFlags(kind), info); 62 masm(), Code::ComputeFlags(kind), info);
64 result->set_is_turbofanned(true); 63 result->set_is_turbofanned(true);
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 for (int i = GapInstruction::FIRST_INNER_POSITION; 165 for (int i = GapInstruction::FIRST_INNER_POSITION;
167 i <= GapInstruction::LAST_INNER_POSITION; i++) { 166 i <= GapInstruction::LAST_INNER_POSITION; i++) {
168 GapInstruction::InnerPosition inner_pos = 167 GapInstruction::InnerPosition inner_pos =
169 static_cast<GapInstruction::InnerPosition>(i); 168 static_cast<GapInstruction::InnerPosition>(i);
170 ParallelMove* move = instr->GetParallelMove(inner_pos); 169 ParallelMove* move = instr->GetParallelMove(inner_pos);
171 if (move != NULL) resolver()->Resolve(move); 170 if (move != NULL) resolver()->Resolve(move);
172 } 171 }
173 } 172 }
174 173
175 174
176 void CodeGenerator::UpdateSafepointsWithDeoptimizationPc() { 175 void CodeGenerator::EmitLazyDeoptimizationCallTable() {
177 int patch_count = static_cast<int>(lazy_deoptimization_entries_.size()); 176 // ZoneDeque<DeoptimizationPoint*>::iterator iter;
178 for (int i = 0; i < patch_count; ++i) { 177 int i = 0;
179 LazyDeoptimizationEntry entry = lazy_deoptimization_entries_[i]; 178 for (ZoneDeque<DeoptimizationPoint*>::iterator
180 // TODO(jarin) make sure that there is no code (other than nops) 179 iter = deoptimization_points_.begin();
181 // between the call position and the continuation position. 180 iter != deoptimization_points_.end(); iter++, i++) {
182 safepoints()->SetDeoptimizationPc(entry.safepoint_id(), 181 int pc_offset = masm()->pc_offset();
183 entry.deoptimization()->pos()); 182 AssembleDeoptimizerCall((*iter)->lazy_state_id());
183 safepoints()->SetDeoptimizationPc((*iter)->safepoint(), pc_offset);
184 } 184 }
185 } 185 }
186 186
187 187
188 void CodeGenerator::PopulateDeoptimizationData(Handle<Code> code_object) { 188 void CodeGenerator::PopulateDeoptimizationData(Handle<Code> code_object) {
189 CompilationInfo* info = linkage()->info(); 189 CompilationInfo* info = linkage()->info();
190 int deopt_count = code()->GetDeoptimizationEntryCount(); 190 int deopt_count = static_cast<int>(deoptimization_states_.size());
191 int patch_count = static_cast<int>(lazy_deoptimization_entries_.size()); 191 if (deopt_count == 0) return;
192 if (patch_count == 0 && deopt_count == 0) return;
193 Handle<DeoptimizationInputData> data = 192 Handle<DeoptimizationInputData> data =
194 DeoptimizationInputData::New(isolate(), deopt_count, TENURED); 193 DeoptimizationInputData::New(isolate(), deopt_count, TENURED);
195 194
196 Handle<ByteArray> translation_array = 195 Handle<ByteArray> translation_array =
197 translations_.CreateByteArray(isolate()->factory()); 196 translations_.CreateByteArray(isolate()->factory());
198 197
199 data->SetTranslationByteArray(*translation_array); 198 data->SetTranslationByteArray(*translation_array);
200 data->SetInlinedFunctionCount(Smi::FromInt(0)); 199 data->SetInlinedFunctionCount(Smi::FromInt(0));
201 data->SetOptimizationId(Smi::FromInt(info->optimization_id())); 200 data->SetOptimizationId(Smi::FromInt(info->optimization_id()));
202 // TODO(jarin) The following code was copied over from Lithium, not sure 201 // TODO(jarin) The following code was copied over from Lithium, not sure
(...skipping 16 matching lines...) Expand all
219 data->SetLiteralArray(*literals); 218 data->SetLiteralArray(*literals);
220 } 219 }
221 220
222 // No OSR in Turbofan yet... 221 // No OSR in Turbofan yet...
223 BailoutId osr_ast_id = BailoutId::None(); 222 BailoutId osr_ast_id = BailoutId::None();
224 data->SetOsrAstId(Smi::FromInt(osr_ast_id.ToInt())); 223 data->SetOsrAstId(Smi::FromInt(osr_ast_id.ToInt()));
225 data->SetOsrPcOffset(Smi::FromInt(-1)); 224 data->SetOsrPcOffset(Smi::FromInt(-1));
226 225
227 // Populate deoptimization entries. 226 // Populate deoptimization entries.
228 for (int i = 0; i < deopt_count; i++) { 227 for (int i = 0; i < deopt_count; i++) {
229 FrameStateDescriptor* descriptor = code()->GetDeoptimizationEntry(i); 228 DeoptimizationState* deoptimization_state = deoptimization_states_[i];
230 data->SetAstId(i, descriptor->bailout_id()); 229 data->SetAstId(i, deoptimization_state->bailout_id());
231 CHECK_NE(NULL, deoptimization_states_[i]); 230 CHECK_NE(NULL, deoptimization_states_[i]);
232 data->SetTranslationIndex( 231 data->SetTranslationIndex(
233 i, Smi::FromInt(deoptimization_states_[i]->translation_id_)); 232 i, Smi::FromInt(deoptimization_states_[i]->translation_id()));
234 data->SetArgumentsStackHeight(i, Smi::FromInt(0)); 233 data->SetArgumentsStackHeight(i, Smi::FromInt(0));
235 data->SetPc(i, Smi::FromInt(-1)); 234 data->SetPc(i, Smi::FromInt(-1));
236 } 235 }
237 236
238 code_object->set_deoptimization_data(*data); 237 code_object->set_deoptimization_data(*data);
239 } 238 }
240 239
241 240
242 void CodeGenerator::AddSafepointAndDeopt(Instruction* instr) { 241 void CodeGenerator::AddSafepointAndDeopt(Instruction* instr) {
243 CallDescriptor::Flags flags(MiscField::decode(instr->opcode())); 242 CallDescriptor::Flags flags(MiscField::decode(instr->opcode()));
244 243
245 bool needs_frame_state = (flags & CallDescriptor::kNeedsFrameState); 244 bool needs_frame_state = (flags & CallDescriptor::kNeedsFrameState);
246 245
247 Safepoint::Id safepoint_id = RecordSafepoint( 246 Safepoint::Id safepoint_id = RecordSafepoint(
248 instr->pointer_map(), Safepoint::kSimple, 0, 247 instr->pointer_map(), Safepoint::kSimple, 0,
249 needs_frame_state ? Safepoint::kLazyDeopt : Safepoint::kNoLazyDeopt); 248 needs_frame_state ? Safepoint::kLazyDeopt : Safepoint::kNoLazyDeopt);
250 249
251 if (flags & CallDescriptor::kLazyDeoptimization) {
252 RecordLazyDeoptimizationEntry(instr, safepoint_id);
253 }
254
255 if (needs_frame_state) { 250 if (needs_frame_state) {
256 // If the frame state is present, it starts at argument 1 251 // If the frame state is present, it starts at argument 1
257 // (just after the code address). 252 // (just after the code address).
258 InstructionOperandConverter converter(this, instr); 253 InstructionOperandConverter converter(this, instr);
259 // Deoptimization info starts at argument 1 254 // Deoptimization info starts at argument 1
260 int frame_state_offset = 1; 255 int frame_state_offset = 1;
261 int deoptimization_id = BuildTranslation(instr, frame_state_offset); 256 FrameStateDescriptor* descriptor =
257 GetFrameStateDescriptor(instr, frame_state_offset);
258 int deopt_state_id =
259 BuildTranslation(instr, frame_state_offset, kIgnoreOutput);
260 int lazy_deopt_state_id = deopt_state_id;
261 if (descriptor->state_combine() != kIgnoreOutput) {
262 lazy_deopt_state_id = BuildTranslation(instr, frame_state_offset,
263 descriptor->state_combine());
264 }
265 deoptimization_points_.push_back(new (zone()) DeoptimizationPoint(
266 deopt_state_id, lazy_deopt_state_id, descriptor, safepoint_id));
262 #if DEBUG 267 #if DEBUG
263 // Make sure all the values live in stack slots or they are immediates. 268 // Make sure all the values live in stack slots or they are immediates.
264 // (The values should not live in register because registers are clobbered 269 // (The values should not live in register because registers are clobbered
265 // by calls.) 270 // by calls.)
266 FrameStateDescriptor* descriptor =
267 code()->GetDeoptimizationEntry(deoptimization_id);
268 for (int i = 0; i < descriptor->size(); i++) { 271 for (int i = 0; i < descriptor->size(); i++) {
269 InstructionOperand* op = instr->InputAt(frame_state_offset + 1 + i); 272 InstructionOperand* op = instr->InputAt(frame_state_offset + 1 + i);
270 CHECK(op->IsStackSlot() || op->IsImmediate()); 273 CHECK(op->IsStackSlot() || op->IsImmediate());
271 } 274 }
272 #endif 275 #endif
273 safepoints()->RecordLazyDeoptimizationIndex(deoptimization_id); 276 safepoints()->RecordLazyDeoptimizationIndex(lazy_deopt_state_id);
274 } 277 }
275 278
276 if (flags & CallDescriptor::kNeedsNopAfterCall) { 279 if (flags & CallDescriptor::kNeedsNopAfterCall) {
277 AddNopForSmiCodeInlining(); 280 AddNopForSmiCodeInlining();
278 } 281 }
279 } 282 }
280 283
281 284
282 void CodeGenerator::RecordLazyDeoptimizationEntry(Instruction* instr,
283 Safepoint::Id safepoint_id) {
284 InstructionOperandConverter i(this, instr);
285
286 Label after_call;
287 masm()->bind(&after_call);
288
289 // The continuation and deoptimization are the last two inputs:
290 BasicBlock* cont_block =
291 i.InputBlock(static_cast<int>(instr->InputCount()) - 2);
292 BasicBlock* deopt_block =
293 i.InputBlock(static_cast<int>(instr->InputCount()) - 1);
294
295 Label* cont_label = code_->GetLabel(cont_block);
296 Label* deopt_label = code_->GetLabel(deopt_block);
297
298 lazy_deoptimization_entries_.push_back(LazyDeoptimizationEntry(
299 after_call.pos(), cont_label, deopt_label, safepoint_id));
300 }
301
302
303 int CodeGenerator::DefineDeoptimizationLiteral(Handle<Object> literal) { 285 int CodeGenerator::DefineDeoptimizationLiteral(Handle<Object> literal) {
304 int result = static_cast<int>(deoptimization_literals_.size()); 286 int result = static_cast<int>(deoptimization_literals_.size());
305 for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) { 287 for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) {
306 if (deoptimization_literals_[i].is_identical_to(literal)) return i; 288 if (deoptimization_literals_[i].is_identical_to(literal)) return i;
307 } 289 }
308 deoptimization_literals_.push_back(literal); 290 deoptimization_literals_.push_back(literal);
309 return result; 291 return result;
310 } 292 }
311 293
312 294
313 int CodeGenerator::BuildTranslation(Instruction* instr, 295 FrameStateDescriptor* CodeGenerator::GetFrameStateDescriptor(
314 int frame_state_offset) { 296 Instruction* instr, int frame_state_offset) {
315 InstructionOperandConverter i(this, instr); 297 InstructionOperandConverter i(this, instr);
316 int deoptimization_id = i.InputInt32(frame_state_offset); 298 InstructionSequence::StateId state_id =
299 InstructionSequence::StateId::FromInt(i.InputInt32(frame_state_offset));
300 return code()->GetFrameStateDescriptor(state_id);
301 }
302
303
304 int CodeGenerator::BuildTranslation(Instruction* instr, int frame_state_offset,
305 OutputFrameStateCombine state_combine) {
306 FrameStateDescriptor* descriptor =
307 GetFrameStateDescriptor(instr, frame_state_offset);
317 frame_state_offset++; 308 frame_state_offset++;
318 309
319 // We should build translation only once. 310 int height = descriptor->size() - descriptor->parameters_count();
320 DCHECK_EQ(NULL, deoptimization_states_[deoptimization_id]); 311 switch (state_combine) {
312 case kPushOutput:
313 height++;
314 break;
315 case kIgnoreOutput:
316 break;
317 }
321 318
322 FrameStateDescriptor* descriptor = 319
323 code()->GetDeoptimizationEntry(deoptimization_id);
324 Translation translation(&translations_, 1, 1, zone()); 320 Translation translation(&translations_, 1, 1, zone());
325 translation.BeginJSFrame(descriptor->bailout_id(), 321 translation.BeginJSFrame(descriptor->bailout_id(),
326 Translation::kSelfLiteralId, 322 Translation::kSelfLiteralId, height);
327 descriptor->size() - descriptor->parameters_count());
328 323
329 for (int i = 0; i < descriptor->size(); i++) { 324 for (int i = 0; i < descriptor->size(); i++) {
330 AddTranslationForOperand(&translation, instr, 325 AddTranslationForOperand(&translation, instr,
331 instr->InputAt(i + frame_state_offset)); 326 instr->InputAt(i + frame_state_offset));
332 } 327 }
333 328
334 deoptimization_states_[deoptimization_id] = 329 switch (state_combine) {
335 new (zone()) DeoptimizationState(translation.index()); 330 case kPushOutput:
331 DCHECK(instr->OutputCount() == 1);
332 AddTranslationForOperand(&translation, instr, instr->OutputAt(0));
333 break;
334 case kIgnoreOutput:
335 break;
336 }
337
338 int deoptimization_id = static_cast<int>(deoptimization_states_.size());
339
340 deoptimization_states_.push_back(new (zone()) DeoptimizationState(
341 descriptor->bailout_id(), translation.index()));
336 342
337 return deoptimization_id; 343 return deoptimization_id;
338 } 344 }
339 345
340 346
341 void CodeGenerator::AddTranslationForOperand(Translation* translation, 347 void CodeGenerator::AddTranslationForOperand(Translation* translation,
342 Instruction* instr, 348 Instruction* instr,
343 InstructionOperand* op) { 349 InstructionOperand* op) {
344 if (op->IsStackSlot()) { 350 if (op->IsStackSlot()) {
345 translation->StoreStackSlot(op->index()); 351 translation->StoreStackSlot(op->index());
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 } 420 }
415 421
416 422
417 void CodeGenerator::AddNopForSmiCodeInlining() { UNIMPLEMENTED(); } 423 void CodeGenerator::AddNopForSmiCodeInlining() { UNIMPLEMENTED(); }
418 424
419 #endif // !V8_TURBOFAN_BACKEND 425 #endif // !V8_TURBOFAN_BACKEND
420 426
421 } // namespace compiler 427 } // namespace compiler
422 } // namespace internal 428 } // namespace internal
423 } // namespace v8 429 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/code-generator.h ('k') | src/compiler/common-operator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698