OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 | 78 |
79 bool LCodeGen::GenerateCode() { | 79 bool LCodeGen::GenerateCode() { |
80 HPhase phase("Code generation", chunk()); | 80 HPhase phase("Code generation", chunk()); |
81 ASSERT(is_unused()); | 81 ASSERT(is_unused()); |
82 status_ = GENERATING; | 82 status_ = GENERATING; |
83 CpuFeatures::Scope scope1(VFP3); | 83 CpuFeatures::Scope scope1(VFP3); |
84 CpuFeatures::Scope scope2(ARMv7); | 84 CpuFeatures::Scope scope2(ARMv7); |
85 return GeneratePrologue() && | 85 return GeneratePrologue() && |
86 GenerateBody() && | 86 GenerateBody() && |
87 GenerateDeferredCode() && | 87 GenerateDeferredCode() && |
88 GenerateDeoptJumpTable() && | |
88 GenerateSafepointTable(); | 89 GenerateSafepointTable(); |
89 } | 90 } |
90 | 91 |
91 | 92 |
92 void LCodeGen::FinishCode(Handle<Code> code) { | 93 void LCodeGen::FinishCode(Handle<Code> code) { |
93 ASSERT(is_done()); | 94 ASSERT(is_done()); |
94 code->set_stack_slots(GetStackSlotCount()); | 95 code->set_stack_slots(GetStackSlotCount()); |
95 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 96 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
96 PopulateDeoptimizationData(code); | 97 PopulateDeoptimizationData(code); |
97 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); | 98 Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
242 | 243 |
243 bool LCodeGen::GenerateDeferredCode() { | 244 bool LCodeGen::GenerateDeferredCode() { |
244 ASSERT(is_generating()); | 245 ASSERT(is_generating()); |
245 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 246 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
246 LDeferredCode* code = deferred_[i]; | 247 LDeferredCode* code = deferred_[i]; |
247 __ bind(code->entry()); | 248 __ bind(code->entry()); |
248 code->Generate(); | 249 code->Generate(); |
249 __ jmp(code->exit()); | 250 __ jmp(code->exit()); |
250 } | 251 } |
251 | 252 |
252 // Force constant pool emission at the end of deferred code to make | 253 return !is_aborted(); |
254 } | |
255 | |
256 | |
257 bool LCodeGen::GenerateDeoptJumpTable() { | |
258 // Emit previous constant pool entries so that we can safely emit the | |
259 // deoptimization jump table. | |
260 masm()->CheckConstPool(true, false); | |
261 // Check that the jump table is accessible from everywhere in the function | |
262 // code, ie that offsets to the table can be encoded in the 24bit signed | |
263 // immediate of a branch instruction. | |
264 // To simplify we consider the code size from the first instruction to the | |
265 // end of the jump table. We also don't consider the pc load delta. | |
266 // Each entry in the jump table generates only one instruction. | |
267 if (!is_int24((masm()->pc_offset() / Assembler::kInstrSize) + | |
268 deopt_jump_table_.length())) { | |
269 Abort("Generated code is too large"); | |
270 } | |
271 // We also need to check that the jump table will require fewer constant | |
Søren Thygesen Gjesse
2011/05/18 06:47:13
I think we can avoid this restriction - see below.
Alexandre
2011/05/18 09:13:07
Removed.
On 2011/05/18 06:47:13, Søren Gjesse wro
| |
272 // pool entries than the maximum authorized. | |
273 // Each deopt entry will require exactly one constant pool entry. | |
274 if (deopt_jump_table_.length() > Assembler::MaxNumPRInfo()) { | |
275 Abort("Too many deoptimization entries"); | |
276 } | |
277 | |
278 // Block the constant pool emission during the jump table emission. | |
279 __ BlockConstPoolFor(deopt_jump_table_.length()); | |
280 __ RecordComment("[ Deoptimisation jump table"); | |
281 Label table_start; | |
282 __ bind(&table_start); | |
283 for (int i = 0; i < deopt_jump_table_.length(); i++) { | |
284 __ bind(&deopt_jump_table_[i].label); | |
Søren Thygesen Gjesse
2011/05/18 06:47:13
How about avoiding using the const pool all togeth
Alexandre
2011/05/18 09:13:07
Done.
I also moved back the forced emission of the
| |
285 __ mov(pc, Operand(reinterpret_cast<int32_t>(deopt_jump_table_[i].address), | |
286 RelocInfo::RUNTIME_ENTRY)); | |
287 } | |
288 ASSERT(masm()->InstructionsGeneratedSince(&table_start) == | |
289 deopt_jump_table_.length()); | |
290 __ RecordComment("]"); | |
291 | |
292 // Force constant pool emission at the end of the jump table to make | |
253 // sure that no constant pools are emitted after the official end of | 293 // sure that no constant pools are emitted after the official end of |
254 // the instruction sequence. | 294 // the instruction sequence. |
255 masm()->CheckConstPool(true, false); | 295 masm()->CheckConstPool(true, false); |
256 | 296 |
257 // Deferred code is the last part of the instruction sequence. Mark | 297 // The deoptimization jump table is the last part of the instruction |
258 // the generated code as done unless we bailed out. | 298 // sequence. Mark the generated code as done unless we bailed out. |
259 if (!is_aborted()) status_ = DONE; | 299 if (!is_aborted()) status_ = DONE; |
260 return !is_aborted(); | 300 return !is_aborted(); |
261 } | 301 } |
262 | 302 |
263 | 303 |
264 bool LCodeGen::GenerateSafepointTable() { | 304 bool LCodeGen::GenerateSafepointTable() { |
265 ASSERT(is_done()); | 305 ASSERT(is_done()); |
266 safepoints_.Emit(masm(), GetStackSlotCount()); | 306 safepoints_.Emit(masm(), GetStackSlotCount()); |
267 return !is_aborted(); | 307 return !is_aborted(); |
268 } | 308 } |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
588 } | 628 } |
589 | 629 |
590 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on ARM. | 630 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on ARM. |
591 | 631 |
592 if (FLAG_deopt_every_n_times == 1 && | 632 if (FLAG_deopt_every_n_times == 1 && |
593 info_->shared_info()->opt_count() == id) { | 633 info_->shared_info()->opt_count() == id) { |
594 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); | 634 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); |
595 return; | 635 return; |
596 } | 636 } |
597 | 637 |
638 if (FLAG_trap_on_deopt) __ stop("trap_on_deopt", cc); | |
639 | |
598 if (cc == al) { | 640 if (cc == al) { |
599 if (FLAG_trap_on_deopt) __ stop("trap_on_deopt"); | |
600 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); | 641 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); |
601 } else { | 642 } else { |
602 if (FLAG_trap_on_deopt) { | 643 // We often have several deopts to the same entry, reuse the last |
603 Label done; | 644 // jump entry if this is the case. |
604 __ b(&done, NegateCondition(cc)); | 645 if (deopt_jump_table_.is_empty() || |
605 __ stop("trap_on_deopt"); | 646 (deopt_jump_table_.last().address != entry)) { |
606 __ Jump(entry, RelocInfo::RUNTIME_ENTRY); | 647 deopt_jump_table_.Add(JumpTableEntry(entry)); |
607 __ bind(&done); | |
608 } else { | |
609 __ Jump(entry, RelocInfo::RUNTIME_ENTRY, cc); | |
610 } | 648 } |
649 __ b(cc, &deopt_jump_table_.last().label); | |
611 } | 650 } |
612 } | 651 } |
613 | 652 |
614 | 653 |
615 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 654 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
616 int length = deoptimizations_.length(); | 655 int length = deoptimizations_.length(); |
617 if (length == 0) return; | 656 if (length == 0) return; |
618 ASSERT(FLAG_deopt); | 657 ASSERT(FLAG_deopt); |
619 Handle<DeoptimizationInputData> data = | 658 Handle<DeoptimizationInputData> data = |
620 factory()->NewDeoptimizationInputData(length, TENURED); | 659 factory()->NewDeoptimizationInputData(length, TENURED); |
(...skipping 3845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4466 ASSERT(osr_pc_offset_ == -1); | 4505 ASSERT(osr_pc_offset_ == -1); |
4467 osr_pc_offset_ = masm()->pc_offset(); | 4506 osr_pc_offset_ = masm()->pc_offset(); |
4468 } | 4507 } |
4469 | 4508 |
4470 | 4509 |
4471 | 4510 |
4472 | 4511 |
4473 #undef __ | 4512 #undef __ |
4474 | 4513 |
4475 } } // namespace v8::internal | 4514 } } // namespace v8::internal |
OLD | NEW |