Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #include "src/compiler/code-generator.h"
6 :
7 : #include "src/address-map.h"
8 : #include "src/assembler-inl.h"
9 : #include "src/base/adapters.h"
10 : #include "src/compilation-info.h"
11 : #include "src/compiler/code-generator-impl.h"
12 : #include "src/compiler/linkage.h"
13 : #include "src/compiler/pipeline.h"
14 : #include "src/eh-frame.h"
15 : #include "src/frames.h"
16 : #include "src/macro-assembler-inl.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 : namespace compiler {
21 :
22 : class CodeGenerator::JumpTable final : public ZoneObject {
23 : public:
24 : JumpTable(JumpTable* next, Label** targets, size_t target_count)
25 7807 : : next_(next), targets_(targets), target_count_(target_count) {}
26 :
27 : Label* label() { return &label_; }
28 : JumpTable* next() const { return next_; }
29 : Label** targets() const { return targets_; }
30 : size_t target_count() const { return target_count_; }
31 :
32 : private:
33 : Label label_;
34 : JumpTable* const next_;
35 : Label** const targets_;
36 : size_t const target_count_;
37 : };
38 :
39 1301551 : CodeGenerator::CodeGenerator(Zone* codegen_zone, Frame* frame, Linkage* linkage,
40 16948857 : InstructionSequence* code, CompilationInfo* info,
41 : base::Optional<OsrHelper> osr_helper,
42 : int start_source_position,
43 9110730 : JumpOptimizationInfo* jump_opt)
44 : : zone_(codegen_zone),
45 : frame_access_state_(nullptr),
46 : linkage_(linkage),
47 : code_(code),
48 : unwinding_info_writer_(zone()),
49 : info_(info),
50 1301489 : labels_(zone()->NewArray<Label>(code->InstructionBlockCount())),
51 : current_block_(RpoNumber::Invalid()),
52 : start_source_position_(start_source_position),
53 : current_source_position_(SourcePosition::Unknown()),
54 : tasm_(info->isolate(), nullptr, 0, CodeObjectRequired::kNo),
55 : resolver_(this),
56 : safepoints_(zone()),
57 : handlers_(zone()),
58 : deoptimization_exits_(zone()),
59 : deoptimization_states_(zone()),
60 : deoptimization_literals_(zone()),
61 : inlined_function_count_(0),
62 : translations_(zone()),
63 : last_lazy_deopt_pc_(0),
64 : caller_registers_saved_(false),
65 : jump_tables_(nullptr),
66 : ools_(nullptr),
67 : osr_helper_(osr_helper),
68 : osr_pc_offset_(-1),
69 : optimized_out_literal_id_(-1),
70 : source_position_table_builder_(zone(),
71 : info->SourcePositionRecordingMode()),
72 14316878 : result_(kSuccess) {
73 28691692 : for (int i = 0; i < code->InstructionBlockCount(); ++i) {
74 13044302 : new (&labels_[i]) Label;
75 : }
76 1301544 : CreateFrameAccessState(frame);
77 1301515 : CHECK_EQ(info->is_osr(), osr_helper_.has_value());
78 : tasm_.set_jump_optimization_info(jump_opt);
79 1301515 : }
80 :
81 17405244 : Isolate* CodeGenerator::isolate() const { return info_->isolate(); }
82 :
83 2603104 : void CodeGenerator::CreateFrameAccessState(Frame* frame) {
84 1301555 : FinishFrame(frame);
85 1301552 : frame_access_state_ = new (zone()) FrameAccessState(frame);
86 1301552 : }
87 :
88 3087686 : CodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall(
89 3087701 : int deoptimization_id, SourcePosition pos) {
90 3087686 : DeoptimizeKind deopt_kind = GetDeoptimizationKind(deoptimization_id);
91 : Deoptimizer::BailoutType bailout_type;
92 3087686 : switch (deopt_kind) {
93 : case DeoptimizeKind::kSoft: {
94 : bailout_type = Deoptimizer::SOFT;
95 : break;
96 : }
97 : case DeoptimizeKind::kEager: {
98 : bailout_type = Deoptimizer::EAGER;
99 315586 : break;
100 : }
101 : case DeoptimizeKind::kLazy: {
102 : bailout_type = Deoptimizer::LAZY;
103 2733716 : break;
104 : }
105 0 : default: { UNREACHABLE(); }
106 : }
107 : DeoptimizeReason deoptimization_reason =
108 3087686 : GetDeoptimizationReason(deoptimization_id);
109 : Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
110 3087690 : tasm()->isolate(), deoptimization_id, bailout_type);
111 3087697 : if (deopt_entry == nullptr) return kTooManyDeoptimizationBailouts;
112 3087701 : if (info()->is_source_positions_enabled()) {
113 236611 : tasm()->RecordDeoptReason(deoptimization_reason, pos, deoptimization_id);
114 : }
115 : tasm()->CallForDeoptimization(deopt_entry, RelocInfo::RUNTIME_ENTRY);
116 3087701 : return kSuccess;
117 : }
118 :
119 35592148 : void CodeGenerator::AssembleCode() {
120 1301537 : CompilationInfo* info = this->info();
121 :
122 : // Open a frame scope to indicate that there is a frame on the stack. The
123 : // MANUAL indicates that the scope shouldn't actually generate code to set up
124 : // the frame (that is done in AssemblePrologue).
125 1301517 : FrameScope frame_scope(tasm(), StackFrame::MANUAL);
126 :
127 1301527 : if (info->is_source_positions_enabled()) {
128 21334 : AssembleSourcePosition(start_source_position());
129 : }
130 :
131 : // Place function entry hook if requested to do so.
132 1301544 : if (linkage()->GetIncomingDescriptor()->IsJSFunctionCall()) {
133 619720 : ProfileEntryHookStub::MaybeCallEntryHookDelayed(tasm(), zone());
134 : }
135 :
136 : // TODO(jupvfranco): This should be the first thing in the code,
137 : // or otherwise MaybeCallEntryHookDelayed may happen twice (for
138 : // optimized and deoptimized code).
139 : // We want to bailout only from JS functions, which are the only ones
140 : // that are optimized.
141 1301537 : if (info->IsOptimizing()) {
142 : DCHECK(linkage()->GetIncomingDescriptor()->IsJSFunctionCall());
143 443353 : BailoutIfDeoptimized();
144 : }
145 :
146 : // Define deoptimization literals for all inlined functions.
147 : DCHECK_EQ(0u, deoptimization_literals_.size());
148 2664592 : for (CompilationInfo::InlinedFunctionHolder& inlined :
149 : info->inlined_functions()) {
150 61528 : if (!inlined.shared_info.equals(info->shared_info())) {
151 : int index = DefineDeoptimizationLiteral(
152 61472 : DeoptimizationLiteral(inlined.shared_info));
153 : inlined.RegisterInlinedFunctionId(index);
154 : }
155 : }
156 1301532 : inlined_function_count_ = deoptimization_literals_.size();
157 :
158 : unwinding_info_writer_.SetNumberOfInstructionBlocks(
159 1301532 : code()->InstructionBlockCount());
160 :
161 : // Assemble all non-deferred blocks, followed by deferred ones.
162 2603021 : for (int deferred = 0; deferred < 2; ++deferred) {
163 57383588 : for (const InstructionBlock* block : code()->instruction_blocks()) {
164 26088700 : if (block->IsDeferred() == (deferred == 0)) {
165 : continue;
166 : }
167 :
168 : // Align loop headers on 16-byte boundaries.
169 13044402 : if (block->IsLoopHeader() && !tasm()->jump_optimization_info()) {
170 50977 : tasm()->Align(16);
171 : }
172 : // Bind a label for a block.
173 13044404 : current_block_ = block->rpo_number();
174 26088808 : unwinding_info_writer_.BeginInstructionBlock(tasm()->pc_offset(), block);
175 13044410 : if (FLAG_code_comments) {
176 : // TODO(titzer): these code comments are a giant memory leak.
177 : Vector<char> buffer = Vector<char>::New(200);
178 : char* buffer_start = buffer.start();
179 :
180 : int next = SNPrintF(
181 : buffer, "-- B%d start%s%s%s%s", block->rpo_number().ToInt(),
182 : block->IsDeferred() ? " (deferred)" : "",
183 : block->needs_frame() ? "" : " (no frame)",
184 : block->must_construct_frame() ? " (construct frame)" : "",
185 0 : block->must_deconstruct_frame() ? " (deconstruct frame)" : "");
186 :
187 0 : buffer = buffer.SubVector(next, buffer.length());
188 :
189 0 : if (block->IsLoopHeader()) {
190 : next =
191 0 : SNPrintF(buffer, " (loop up to %d)", block->loop_end().ToInt());
192 0 : buffer = buffer.SubVector(next, buffer.length());
193 : }
194 0 : if (block->loop_header().IsValid()) {
195 : next =
196 0 : SNPrintF(buffer, " (in loop %d)", block->loop_header().ToInt());
197 0 : buffer = buffer.SubVector(next, buffer.length());
198 : }
199 0 : SNPrintF(buffer, " --");
200 0 : tasm()->RecordComment(buffer_start);
201 : }
202 :
203 26088820 : frame_access_state()->MarkHasFrame(block->needs_frame());
204 :
205 13044429 : tasm()->bind(GetLabel(current_block_));
206 13044448 : if (block->must_construct_frame()) {
207 1074666 : AssembleConstructFrame();
208 : // We need to setup the root register after we assemble the prologue, to
209 : // avoid clobbering callee saved registers in case of C linkage and
210 : // using the roots.
211 : // TODO(mtrofin): investigate how we can avoid doing this repeatedly.
212 1074671 : if (linkage()->GetIncomingDescriptor()->InitializeRootRegister()) {
213 205101 : tasm()->InitializeRootRegister();
214 : }
215 : }
216 :
217 : if (FLAG_enable_embedded_constant_pool && !block->needs_frame()) {
218 : ConstantPoolUnavailableScope constant_pool_unavailable(tasm());
219 : result_ = AssembleBlock(block);
220 : } else {
221 13044453 : result_ = AssembleBlock(block);
222 : }
223 14345875 : if (result_ != kSuccess) return;
224 13044461 : unwinding_info_writer_.EndInstructionBlock(block);
225 : }
226 : }
227 :
228 : // Assemble all out-of-line code.
229 1301552 : if (ools_) {
230 226661 : tasm()->RecordComment("-- Out of line code --");
231 872679 : for (OutOfLineCode* ool = ools_; ool; ool = ool->next()) {
232 646024 : tasm()->bind(ool->entry());
233 646064 : ool->Generate();
234 646063 : if (ool->exit()->is_bound()) tasm()->jmp(ool->exit());
235 : }
236 : }
237 :
238 : // This nop operation is needed to ensure that the trampoline is not
239 : // confused with the pc of the call before deoptimization.
240 : // The test regress/regress-259 is an example of where we need it.
241 1301546 : tasm()->nop();
242 :
243 : // Assemble deoptimization exits.
244 : int last_updated = 0;
245 10409303 : for (DeoptimizationExit* exit : deoptimization_exits_) {
246 3036024 : tasm()->bind(exit->label());
247 3036030 : int trampoline_pc = tasm()->pc_offset();
248 : int deoptimization_id = exit->deoptimization_id();
249 5769743 : DeoptimizationState* ds = deoptimization_states_[deoptimization_id];
250 :
251 3036029 : if (ds->kind() == DeoptimizeKind::kLazy) {
252 : last_updated = safepoints()->UpdateDeoptimizationInfo(
253 2733714 : ds->pc_offset(), trampoline_pc, last_updated);
254 : }
255 3036030 : AssembleDeoptimizerCall(deoptimization_id, exit->pos());
256 : }
257 :
258 1301225 : FinishCode();
259 :
260 : // Emit the jump tables.
261 1301316 : if (jump_tables_) {
262 4271 : tasm()->Align(kPointerSize);
263 19885 : for (JumpTable* table = jump_tables_; table; table = table->next()) {
264 7807 : tasm()->bind(table->label());
265 7807 : AssembleJumpTable(table->targets(), table->target_count());
266 : }
267 : }
268 :
269 : // The PerfJitLogger logs code up until here, excluding the safepoint
270 : // table. Resolve the unwinding info now so it is aware of the same code size
271 : // as reported by perf.
272 1301316 : unwinding_info_writer_.Finish(tasm()->pc_offset());
273 :
274 1301316 : safepoints()->Emit(tasm(), frame()->GetTotalFrameSlotCount());
275 1301387 : result_ = kSuccess;
276 : }
277 :
278 3901633 : Handle<Code> CodeGenerator::FinalizeCode() {
279 1300543 : if (result_ != kSuccess) return Handle<Code>();
280 :
281 : // Allocate exception handler table.
282 1300543 : Handle<HandlerTable> table = HandlerTable::Empty(isolate());
283 1623045 : if (!handlers_.empty()) {
284 : table = Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray(
285 : HandlerTable::LengthForReturn(static_cast<int>(handlers_.size())),
286 24184 : TENURED));
287 334594 : for (size_t i = 0; i < handlers_.size(); ++i) {
288 310410 : table->SetReturnOffset(static_cast<int>(i), handlers_[i].pc_offset);
289 310410 : table->SetReturnHandler(static_cast<int>(i), handlers_[i].handler->pos());
290 : }
291 : }
292 :
293 : // Allocate the source position table.
294 : Handle<ByteArray> source_positions =
295 1300543 : source_position_table_builder_.ToSourcePositionTable(isolate());
296 :
297 : // Allocate deoptimization data.
298 1300544 : Handle<DeoptimizationData> deopt_data = GenerateDeoptimizationData();
299 :
300 : // Allocate and install the code.
301 : CodeDesc desc;
302 1300545 : tasm()->GetCode(isolate(), &desc);
303 1300545 : if (unwinding_info_writer_.eh_frame_writer()) {
304 21 : unwinding_info_writer_.eh_frame_writer()->GetEhFrame(&desc);
305 : }
306 :
307 : Handle<Code> result =
308 : isolate()->factory()->NewCode(desc, info()->code_kind(), Handle<Object>(),
309 2601090 : table, source_positions, deopt_data, false);
310 : isolate()->counters()->total_compiled_code_size()->Increment(
311 1300545 : result->instruction_size());
312 : result->set_is_turbofanned(true);
313 2601090 : result->set_stack_slots(frame()->GetTotalFrameSlotCount());
314 2601090 : result->set_safepoint_table_offset(safepoints()->GetCodeOffset());
315 :
316 2601188 : LOG_CODE_EVENT(isolate(),
317 : CodeLinePosInfoRecordEvent(*Handle<AbstractCode>::cast(result),
318 : *source_positions));
319 :
320 1300545 : return result;
321 : }
322 :
323 :
324 10632484 : bool CodeGenerator::IsNextInAssemblyOrder(RpoNumber block) const {
325 : return code()
326 : ->InstructionBlockAt(current_block_)
327 10632547 : ->ao_number()
328 21265043 : .IsNext(code()->InstructionBlockAt(block)->ao_number());
329 : }
330 :
331 :
332 4710808 : void CodeGenerator::RecordSafepoint(ReferenceMap* references,
333 : Safepoint::Kind kind, int arguments,
334 12215073 : Safepoint::DeoptMode deopt_mode) {
335 : Safepoint safepoint =
336 4710808 : safepoints()->DefineSafepoint(tasm(), kind, arguments, deopt_mode);
337 : int stackSlotToSpillSlotDelta =
338 4710437 : frame()->GetTotalFrameSlotCount() - frame()->GetSpillSlotCount();
339 67495959 : for (const InstructionOperand& operand : references->reference_operands()) {
340 58074627 : if (operand.IsStackSlot()) {
341 : int index = LocationOperand::cast(operand).index();
342 : DCHECK_LE(0, index);
343 : // We might index values in the fixed part of the frame (i.e. the
344 : // closure pointer or the context pointer); these are not spill slots
345 : // and therefore don't work with the SafepointTable currently, but
346 : // we also don't need to worry about them, since the GC has special
347 : // knowledge about those fields anyway.
348 7504834 : if (index < stackSlotToSpillSlotDelta) continue;
349 7504636 : safepoint.DefinePointerSlot(index, zone());
350 50569793 : } else if (operand.IsRegister() && (kind & Safepoint::kWithRegisters)) {
351 0 : Register reg = LocationOperand::cast(operand).GetRegister();
352 0 : safepoint.DefinePointerRegister(reg, zone());
353 : }
354 : }
355 4710895 : }
356 :
357 5300829 : bool CodeGenerator::IsMaterializableFromRoot(
358 5300829 : Handle<HeapObject> object, Heap::RootListIndex* index_return) {
359 : const CallDescriptor* incoming_descriptor =
360 : linkage()->GetIncomingDescriptor();
361 5300829 : if (incoming_descriptor->flags() & CallDescriptor::kCanUseRoots) {
362 : Heap* heap = isolate()->heap();
363 7017131 : return heap->IsRootHandle(object, index_return) &&
364 7017131 : !heap->RootCanBeWrittenAfterInitialization(*index_return);
365 : }
366 : return false;
367 : }
368 :
369 13044381 : CodeGenerator::CodeGenResult CodeGenerator::AssembleBlock(
370 115520295 : const InstructionBlock* block) {
371 115520300 : for (int i = block->code_start(); i < block->code_end(); ++i) {
372 : Instruction* instr = code()->InstructionAt(i);
373 44716017 : CodeGenResult result = AssembleInstruction(instr, block);
374 44715696 : if (result != kSuccess) return result;
375 : }
376 : return kSuccess;
377 : }
378 :
379 44226 : bool CodeGenerator::IsValidPush(InstructionOperand source,
380 : CodeGenerator::PushTypeFlags push_type) {
381 44226 : if (source.IsImmediate() &&
382 : ((push_type & CodeGenerator::kImmediatePush) != 0)) {
383 : return true;
384 : }
385 77736 : if (source.IsRegister() &&
386 : ((push_type & CodeGenerator::kRegisterPush) != 0)) {
387 : return true;
388 : }
389 21302 : if (source.IsStackSlot() &&
390 : ((push_type & CodeGenerator::kStackSlotPush) != 0)) {
391 : return true;
392 : }
393 130 : return false;
394 : }
395 :
396 186607 : void CodeGenerator::GetPushCompatibleMoves(Instruction* instr,
397 : PushTypeFlags push_type,
398 : ZoneVector<MoveOperands*>* pushes) {
399 264761 : pushes->clear();
400 539745 : for (int i = Instruction::FIRST_GAP_POSITION;
401 : i <= Instruction::LAST_GAP_POSITION; ++i) {
402 : Instruction::GapPosition inner_pos =
403 : static_cast<Instruction::GapPosition>(i);
404 : ParallelMove* parallel_move = instr->GetParallelMove(inner_pos);
405 363176 : if (parallel_move != nullptr) {
406 957223 : for (auto move : *parallel_move) {
407 297819 : InstructionOperand source = move->source();
408 297819 : InstructionOperand destination = move->destination();
409 : int first_push_compatible_index =
410 : V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK ? 1 : 0;
411 : // If there are any moves from slots that will be overridden by pushes,
412 : // then the full gap resolver must be used since optimization with
413 : // pushes don't participate in the parallel move and might clobber
414 : // values needed for the gap resolve.
415 318815 : if (source.IsStackSlot() &&
416 : LocationOperand::cast(source).index() >=
417 : first_push_compatible_index) {
418 : pushes->clear();
419 186607 : return;
420 : }
421 : // TODO(danno): Right now, only consider moves from the FIRST gap for
422 : // pushes. Theoretically, we could extract pushes for both gaps (there
423 : // are cases where this happens), but the logic for that would also have
424 : // to check to make sure that non-memory inputs to the pushes from the
425 : // LAST gap don't get clobbered in the FIRST gap.
426 287781 : if (i == Instruction::FIRST_GAP_POSITION) {
427 346302 : if (destination.IsStackSlot() &&
428 : LocationOperand::cast(destination).index() >=
429 : first_push_compatible_index) {
430 : int index = LocationOperand::cast(destination).index();
431 44226 : if (IsValidPush(source, push_type)) {
432 44096 : if (index >= static_cast<int>(pushes->size())) {
433 43724 : pushes->resize(index + 1);
434 : }
435 88192 : (*pushes)[index] = move;
436 : }
437 : }
438 : }
439 : }
440 : }
441 : }
442 :
443 : // For now, only support a set of continuous pushes at the end of the list.
444 : size_t push_count_upper_bound = pushes->size();
445 : size_t push_begin = push_count_upper_bound;
446 267317 : for (auto move : base::Reversed(*pushes)) {
447 50658 : if (move == nullptr) break;
448 40090 : push_begin--;
449 : }
450 176569 : size_t push_count = pushes->size() - push_begin;
451 : std::copy(pushes->begin() + push_begin,
452 : pushes->begin() + push_begin + push_count, pushes->begin());
453 176569 : pushes->resize(push_count);
454 : }
455 :
456 44715984 : CodeGenerator::CodeGenResult CodeGenerator::AssembleInstruction(
457 103654050 : Instruction* instr, const InstructionBlock* block) {
458 : int first_unused_stack_slot;
459 44715984 : FlagsMode mode = FlagsModeField::decode(instr->opcode());
460 44715984 : if (mode != kFlags_trap) {
461 44518425 : AssembleSourcePosition(instr);
462 : }
463 : bool adjust_stack =
464 44716041 : GetSlotAboveSPBeforeTailCall(instr, &first_unused_stack_slot);
465 44716150 : if (adjust_stack) AssembleTailCallBeforeGap(instr, first_unused_stack_slot);
466 44716150 : AssembleGaps(instr);
467 44716138 : if (adjust_stack) AssembleTailCallAfterGap(instr, first_unused_stack_slot);
468 : DCHECK_IMPLIES(
469 : block->must_deconstruct_frame(),
470 : instr != code()->InstructionAt(block->last_instruction_index()) ||
471 : instr->IsRet() || instr->IsJump());
472 48107339 : if (instr->IsJump() && block->must_deconstruct_frame()) {
473 43927 : AssembleDeconstructFrame();
474 : }
475 : // Assemble architecture-specific code for the instruction.
476 44716172 : CodeGenResult result = AssembleArchInstruction(instr);
477 44715622 : if (result != kSuccess) return result;
478 :
479 44715715 : FlagsCondition condition = FlagsConditionField::decode(instr->opcode());
480 44715715 : switch (mode) {
481 : case kFlags_branch: {
482 : // Assemble a branch after this instruction.
483 : InstructionOperandConverter i(this, instr);
484 3610740 : RpoNumber true_rpo = i.InputRpo(instr->InputCount() - 2);
485 3610748 : RpoNumber false_rpo = i.InputRpo(instr->InputCount() - 1);
486 :
487 3610721 : if (true_rpo == false_rpo) {
488 : // redundant branch.
489 1052 : if (!IsNextInAssemblyOrder(true_rpo)) {
490 226 : AssembleArchJump(true_rpo);
491 : }
492 1052 : return kSuccess;
493 : }
494 3609669 : if (IsNextInAssemblyOrder(true_rpo)) {
495 : // true block is next, can fall through if condition negated.
496 : std::swap(true_rpo, false_rpo);
497 : condition = NegateFlagsCondition(condition);
498 : }
499 : BranchInfo branch;
500 3609697 : branch.condition = condition;
501 3609697 : branch.true_label = GetLabel(true_rpo);
502 3609697 : branch.false_label = GetLabel(false_rpo);
503 3609697 : branch.fallthru = IsNextInAssemblyOrder(false_rpo);
504 : // Assemble architecture-specific branch.
505 3609703 : AssembleArchBranch(instr, &branch);
506 3609654 : break;
507 : }
508 : case kFlags_deoptimize: {
509 : // Assemble a conditional eager deoptimization after this instruction.
510 : InstructionOperandConverter i(this, instr);
511 302307 : size_t frame_state_offset = MiscField::decode(instr->opcode());
512 : DeoptimizationExit* const exit =
513 302307 : AddDeoptimizationExit(instr, frame_state_offset);
514 : Label continue_label;
515 : BranchInfo branch;
516 302298 : branch.condition = condition;
517 302298 : branch.true_label = exit->label();
518 302298 : branch.false_label = &continue_label;
519 302298 : branch.fallthru = true;
520 : // Assemble architecture-specific branch.
521 302298 : AssembleArchDeoptBranch(instr, &branch);
522 302301 : tasm()->bind(&continue_label);
523 : break;
524 : }
525 : case kFlags_set: {
526 : // Assemble a boolean materialization after this instruction.
527 199916 : AssembleArchBoolean(instr, condition);
528 199917 : break;
529 : }
530 : case kFlags_trap: {
531 197684 : AssembleArchTrap(instr, condition);
532 197678 : break;
533 : }
534 : case kFlags_none: {
535 : break;
536 : }
537 : }
538 : return kSuccess;
539 : }
540 :
541 72101208 : void CodeGenerator::AssembleSourcePosition(Instruction* instr) {
542 44686458 : SourcePosition source_position = SourcePosition::Unknown();
543 85153073 : if (instr->IsNop() && instr->AreMovesRedundant()) return;
544 27414750 : if (!code()->GetSourcePosition(instr, &source_position)) return;
545 4219958 : AssembleSourcePosition(source_position);
546 : }
547 :
548 4241234 : void CodeGenerator::AssembleSourcePosition(SourcePosition source_position) {
549 4241234 : if (source_position == current_source_position_) return;
550 2540951 : current_source_position_ = source_position;
551 2540951 : if (!source_position.IsKnown()) return;
552 2540942 : source_position_table_builder_.AddPosition(tasm()->pc_offset(),
553 2540942 : source_position, false);
554 2541011 : if (FLAG_code_comments) {
555 0 : CompilationInfo* info = this->info();
556 0 : if (info->IsStub()) return;
557 0 : std::ostringstream buffer;
558 0 : buffer << "-- ";
559 0 : if (FLAG_trace_turbo || FLAG_trace_turbo_graph ||
560 0 : tasm()->isolate()->concurrent_recompilation_enabled()) {
561 0 : buffer << source_position;
562 : } else {
563 : AllowHeapAllocation allocation;
564 : AllowHandleAllocation handles;
565 : AllowHandleDereference deref;
566 0 : buffer << source_position.InliningStack(info);
567 : }
568 0 : buffer << " --";
569 0 : tasm()->RecordComment(StrDup(buffer.str().c_str()));
570 : }
571 : }
572 :
573 44902720 : bool CodeGenerator::GetSlotAboveSPBeforeTailCall(Instruction* instr,
574 : int* slot) {
575 44716131 : if (instr->IsTailCall()) {
576 : InstructionOperandConverter g(this, instr);
577 186589 : *slot = g.InputInt32(instr->InputCount() - 1);
578 : return true;
579 : } else {
580 : return false;
581 : }
582 : }
583 :
584 44715992 : void CodeGenerator::AssembleGaps(Instruction* instr) {
585 134147913 : for (int i = Instruction::FIRST_GAP_POSITION;
586 : i <= Instruction::LAST_GAP_POSITION; i++) {
587 : Instruction::GapPosition inner_pos =
588 : static_cast<Instruction::GapPosition>(i);
589 : ParallelMove* move = instr->GetParallelMove(inner_pos);
590 89431780 : if (move != nullptr) resolver()->Resolve(move);
591 : }
592 44716133 : }
593 :
594 : namespace {
595 :
596 442528 : Handle<PodArray<InliningPosition>> CreateInliningPositions(
597 442528 : CompilationInfo* info) {
598 517187 : const CompilationInfo::InlinedFunctionList& inlined_functions =
599 : info->inlined_functions();
600 442528 : if (inlined_functions.size() == 0) {
601 : return Handle<PodArray<InliningPosition>>::cast(
602 : info->isolate()->factory()->empty_byte_array());
603 : }
604 : Handle<PodArray<InliningPosition>> inl_positions =
605 : PodArray<InliningPosition>::New(
606 13474 : info->isolate(), static_cast<int>(inlined_functions.size()), TENURED);
607 149318 : for (size_t i = 0; i < inlined_functions.size(); ++i) {
608 61185 : inl_positions->set(static_cast<int>(i), inlined_functions[i].position);
609 : }
610 13474 : return inl_positions;
611 : }
612 :
613 : } // namespace
614 :
615 1300545 : Handle<DeoptimizationData> CodeGenerator::GenerateDeoptimizationData() {
616 442528 : CompilationInfo* info = this->info();
617 1300545 : int deopt_count = static_cast<int>(deoptimization_states_.size());
618 2158562 : if (deopt_count == 0 && !info->is_osr()) {
619 858017 : return DeoptimizationData::Empty(isolate());
620 : }
621 : Handle<DeoptimizationData> data =
622 442528 : DeoptimizationData::New(isolate(), deopt_count, TENURED);
623 :
624 : Handle<ByteArray> translation_array =
625 442528 : translations_.CreateByteArray(isolate()->factory());
626 :
627 : data->SetTranslationByteArray(*translation_array);
628 : data->SetInlinedFunctionCount(
629 442528 : Smi::FromInt(static_cast<int>(inlined_function_count_)));
630 : data->SetOptimizationId(Smi::FromInt(info->optimization_id()));
631 :
632 442528 : if (info->has_shared_info()) {
633 : data->SetSharedFunctionInfo(*info->shared_info());
634 : } else {
635 : data->SetSharedFunctionInfo(Smi::kZero);
636 : }
637 :
638 : Handle<FixedArray> literals = isolate()->factory()->NewFixedArray(
639 885056 : static_cast<int>(deoptimization_literals_.size()), TENURED);
640 3370912 : for (unsigned i = 0; i < deoptimization_literals_.size(); i++) {
641 1242928 : Handle<Object> object = deoptimization_literals_[i].Reify(isolate());
642 2485856 : literals->set(i, *object);
643 : }
644 : data->SetLiteralArray(*literals);
645 :
646 442528 : Handle<PodArray<InliningPosition>> inl_pos = CreateInliningPositions(info);
647 : data->SetInliningPositions(*inl_pos);
648 :
649 442528 : if (info->is_osr()) {
650 : DCHECK_LE(0, osr_pc_offset_);
651 5809 : data->SetOsrBytecodeOffset(Smi::FromInt(info_->osr_offset().ToInt()));
652 5809 : data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
653 : } else {
654 : BailoutId osr_offset = BailoutId::None();
655 : data->SetOsrBytecodeOffset(Smi::FromInt(osr_offset.ToInt()));
656 : data->SetOsrPcOffset(Smi::FromInt(-1));
657 : }
658 :
659 : // Populate deoptimization entries.
660 3077632 : for (int i = 0; i < deopt_count; i++) {
661 9232896 : DeoptimizationState* deoptimization_state = deoptimization_states_[i];
662 : data->SetBytecodeOffset(i, deoptimization_state->bailout_id());
663 3077632 : CHECK(deoptimization_state);
664 : data->SetTranslationIndex(
665 3077632 : i, Smi::FromInt(deoptimization_state->translation_id()));
666 3077632 : data->SetPc(i, Smi::FromInt(deoptimization_state->pc_offset()));
667 : }
668 :
669 442528 : return data;
670 : }
671 :
672 :
673 7807 : Label* CodeGenerator::AddJumpTable(Label** targets, size_t target_count) {
674 15614 : jump_tables_ = new (zone()) JumpTable(jump_tables_, targets, target_count);
675 7807 : return jump_tables_->label();
676 : }
677 :
678 :
679 12130306 : void CodeGenerator::RecordCallPosition(Instruction* instr) {
680 4542767 : CallDescriptor::Flags flags(MiscField::decode(instr->opcode()));
681 :
682 4542767 : bool needs_frame_state = (flags & CallDescriptor::kNeedsFrameState);
683 :
684 : RecordSafepoint(
685 : instr->reference_map(), Safepoint::kSimple, 0,
686 9085534 : needs_frame_state ? Safepoint::kLazyDeopt : Safepoint::kNoLazyDeopt);
687 :
688 4542822 : if (flags & CallDescriptor::kHasExceptionHandler) {
689 : InstructionOperandConverter i(this, instr);
690 155527 : RpoNumber handler_rpo = i.InputRpo(instr->InputCount() - 1);
691 466581 : handlers_.push_back({GetLabel(handler_rpo), tasm()->pc_offset()});
692 : }
693 :
694 4542822 : if (needs_frame_state) {
695 : MarkLazyDeoptSite();
696 : // If the frame state is present, it starts at argument 1 (just after the
697 : // code address).
698 : size_t frame_state_offset = 1;
699 : FrameStateDescriptor* descriptor =
700 2733724 : GetDeoptimizationEntry(instr, frame_state_offset).descriptor();
701 2733718 : int pc_offset = tasm()->pc_offset();
702 : int deopt_state_id = BuildTranslation(instr, pc_offset, frame_state_offset,
703 2733718 : descriptor->state_combine());
704 :
705 : DeoptimizationExit* const exit = new (zone())
706 5467436 : DeoptimizationExit(deopt_state_id, current_source_position_);
707 2733718 : deoptimization_exits_.push_back(exit);
708 2733718 : safepoints()->RecordLazyDeoptimizationIndex(deopt_state_id);
709 : }
710 4542815 : }
711 :
712 6385081 : int CodeGenerator::DefineDeoptimizationLiteral(DeoptimizationLiteral literal) {
713 6385081 : int result = static_cast<int>(deoptimization_literals_.size());
714 57825022 : for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) {
715 27665931 : if (deoptimization_literals_[i] == literal) return i;
716 : }
717 1246582 : deoptimization_literals_.push_back(literal);
718 1246578 : return result;
719 : }
720 :
721 5821395 : DeoptimizationEntry const& CodeGenerator::GetDeoptimizationEntry(
722 5821409 : Instruction* instr, size_t frame_state_offset) {
723 : InstructionOperandConverter i(this, instr);
724 5821395 : int const state_id = i.InputInt32(frame_state_offset);
725 5821409 : return code()->GetDeoptimizationEntry(state_id);
726 : }
727 :
728 3087686 : DeoptimizeKind CodeGenerator::GetDeoptimizationKind(
729 : int deoptimization_id) const {
730 : size_t const index = static_cast<size_t>(deoptimization_id);
731 : DCHECK_LT(index, deoptimization_states_.size());
732 3087686 : return deoptimization_states_[index]->kind();
733 : }
734 :
735 3087683 : DeoptimizeReason CodeGenerator::GetDeoptimizationReason(
736 : int deoptimization_id) const {
737 : size_t const index = static_cast<size_t>(deoptimization_id);
738 : DCHECK_LT(index, deoptimization_states_.size());
739 3087691 : return deoptimization_states_[index]->reason();
740 : }
741 :
742 47795618 : void CodeGenerator::TranslateStateValueDescriptor(
743 47825687 : StateValueDescriptor* desc, StateValueList* nested,
744 : Translation* translation, InstructionOperandIterator* iter) {
745 : // Note:
746 : // If translation is null, we just skip the relevant instruction operands.
747 47795618 : if (desc->IsNested()) {
748 57130 : if (translation != nullptr) {
749 57128 : translation->BeginCapturedObject(static_cast<int>(nested->size()));
750 : }
751 394815 : for (auto field : *nested) {
752 : TranslateStateValueDescriptor(field.desc, field.nested, translation,
753 280555 : iter);
754 : }
755 47738488 : } else if (desc->IsArgumentsElements()) {
756 8973 : if (translation != nullptr) {
757 8973 : translation->ArgumentsElements(desc->arguments_type());
758 : }
759 47729515 : } else if (desc->IsArgumentsLength()) {
760 9276 : if (translation != nullptr) {
761 9276 : translation->ArgumentsLength(desc->arguments_type());
762 : }
763 47720239 : } else if (desc->IsDuplicate()) {
764 11820 : if (translation != nullptr) {
765 11820 : translation->DuplicateObject(static_cast<int>(desc->id()));
766 : }
767 47708419 : } else if (desc->IsPlain()) {
768 20713945 : InstructionOperand* op = iter->Advance();
769 20713945 : if (translation != nullptr) {
770 : AddTranslationForOperand(translation, iter->instruction(), op,
771 20677414 : desc->type());
772 : }
773 : } else {
774 : DCHECK(desc->IsOptimizedOut());
775 26994474 : if (translation != nullptr) {
776 25400881 : if (optimized_out_literal_id_ == -1) {
777 : optimized_out_literal_id_ = DefineDeoptimizationLiteral(
778 441564 : DeoptimizationLiteral(isolate()->factory()->optimized_out()));
779 : }
780 25400881 : translation->StoreLiteral(optimized_out_literal_id_);
781 : }
782 : }
783 47795507 : }
784 :
785 :
786 3360451 : void CodeGenerator::TranslateFrameStateDescriptorOperands(
787 3454228 : FrameStateDescriptor* desc, InstructionOperandIterator* iter,
788 : OutputFrameStateCombine combine, Translation* translation) {
789 : size_t index = 0;
790 : StateValueList* values = desc->GetStateValueDescriptors();
791 101750324 : for (StateValueList::iterator it = values->begin(); it != values->end();
792 : ++it, ++index) {
793 : StateValueDescriptor* value_desc = (*it).desc;
794 47514781 : if (!combine.IsOutputIgnored()) {
795 : // The result of the call should be placed at position
796 : // [index_from_top] in the stack (overwriting whatever was
797 : // previously there).
798 26319106 : size_t index_from_top = desc->GetSize() - 1 - combine.GetOffsetToPokeAt();
799 28143206 : if (index >= index_from_top &&
800 3648188 : index < index_from_top + iter->instruction()->OutputCount()) {
801 : DCHECK_NOT_NULL(translation);
802 : AddTranslationForOperand(
803 : translation, iter->instruction(),
804 : iter->instruction()->OutputAt(index - index_from_top),
805 3260268 : MachineType::AnyTagged());
806 : // Skip the instruction operands.
807 1630134 : TranslateStateValueDescriptor(value_desc, (*it).nested, nullptr, iter);
808 1630134 : continue;
809 : }
810 : }
811 45884653 : TranslateStateValueDescriptor(value_desc, (*it).nested, translation, iter);
812 : }
813 : DCHECK_EQ(desc->GetSize(), index);
814 3360381 : }
815 :
816 :
817 3360352 : void CodeGenerator::BuildTranslationForFrameStateDescriptor(
818 10075749 : FrameStateDescriptor* descriptor, InstructionOperandIterator* iter,
819 1299 : Translation* translation, OutputFrameStateCombine state_combine) {
820 : // Outer-most state must be added to translation first.
821 3360352 : if (descriptor->outer_state() != nullptr) {
822 : BuildTranslationForFrameStateDescriptor(descriptor->outer_state(), iter,
823 : translation,
824 272676 : OutputFrameStateCombine::Ignore());
825 : }
826 :
827 : Handle<SharedFunctionInfo> shared_info;
828 3360354 : if (!descriptor->shared_info().ToHandle(&shared_info)) {
829 1299 : if (!info()->has_shared_info()) {
830 3360383 : return; // Stub with no SharedFunctionInfo.
831 : }
832 : shared_info = info()->shared_info();
833 : }
834 : int shared_info_id =
835 3360354 : DefineDeoptimizationLiteral(DeoptimizationLiteral(shared_info));
836 :
837 3360353 : switch (descriptor->type()) {
838 : case FrameStateType::kInterpretedFunction:
839 : translation->BeginInterpretedFrame(
840 : descriptor->bailout_id(), shared_info_id,
841 3258489 : static_cast<unsigned int>(descriptor->locals_count() + 1));
842 3258513 : break;
843 : case FrameStateType::kArgumentsAdaptor:
844 : translation->BeginArgumentsAdaptorFrame(
845 : shared_info_id,
846 61562 : static_cast<unsigned int>(descriptor->parameters_count()));
847 61562 : break;
848 : case FrameStateType::kConstructStub:
849 : DCHECK(descriptor->bailout_id().IsValidForConstructStub());
850 : translation->BeginConstructStubFrame(
851 : descriptor->bailout_id(), shared_info_id,
852 32279 : static_cast<unsigned int>(descriptor->parameters_count()));
853 32279 : break;
854 : case FrameStateType::kBuiltinContinuation: {
855 1299 : BailoutId bailout_id = descriptor->bailout_id();
856 : int parameter_count =
857 : static_cast<unsigned int>(descriptor->parameters_count());
858 : translation->BeginBuiltinContinuationFrame(bailout_id, shared_info_id,
859 1299 : parameter_count);
860 : break;
861 : }
862 : case FrameStateType::kJavaScriptBuiltinContinuation: {
863 1415 : BailoutId bailout_id = descriptor->bailout_id();
864 : int parameter_count =
865 : static_cast<unsigned int>(descriptor->parameters_count());
866 : translation->BeginJavaScriptBuiltinContinuationFrame(
867 1415 : bailout_id, shared_info_id, parameter_count);
868 : break;
869 : }
870 : case FrameStateType::kGetterStub:
871 2979 : translation->BeginGetterStubFrame(shared_info_id);
872 2979 : break;
873 : case FrameStateType::kSetterStub:
874 2329 : translation->BeginSetterStubFrame(shared_info_id);
875 2329 : break;
876 : }
877 :
878 : TranslateFrameStateDescriptorOperands(descriptor, iter, state_combine,
879 3360377 : translation);
880 : }
881 :
882 :
883 3087678 : int CodeGenerator::BuildTranslation(Instruction* instr, int pc_offset,
884 : size_t frame_state_offset,
885 6175400 : OutputFrameStateCombine state_combine) {
886 6175400 : DeoptimizationEntry const& entry =
887 3087678 : GetDeoptimizationEntry(instr, frame_state_offset);
888 : FrameStateDescriptor* const descriptor = entry.descriptor();
889 3087692 : frame_state_offset++;
890 :
891 : Translation translation(
892 3087701 : &translations_, static_cast<int>(descriptor->GetFrameCount()),
893 6175389 : static_cast<int>(descriptor->GetJSFrameCount()), zone());
894 : InstructionOperandIterator iter(instr, frame_state_offset);
895 : BuildTranslationForFrameStateDescriptor(descriptor, &iter, &translation,
896 3087693 : state_combine);
897 :
898 3087708 : int deoptimization_id = static_cast<int>(deoptimization_states_.size());
899 :
900 : deoptimization_states_.push_back(new (zone()) DeoptimizationState(
901 3087708 : descriptor->bailout_id(), translation.index(), pc_offset, entry.kind(),
902 6175384 : entry.reason()));
903 :
904 3087681 : return deoptimization_id;
905 : }
906 :
907 22307625 : void CodeGenerator::AddTranslationForOperand(Translation* translation,
908 : Instruction* instr,
909 : InstructionOperand* op,
910 5511215 : MachineType type) {
911 22307625 : if (op->IsStackSlot()) {
912 14360151 : if (type.representation() == MachineRepresentation::kBit) {
913 23961 : translation->StoreBoolStackSlot(LocationOperand::cast(op)->index());
914 43008053 : } else if (type == MachineType::Int8() || type == MachineType::Int16() ||
915 : type == MachineType::Int32()) {
916 239055 : translation->StoreInt32StackSlot(LocationOperand::cast(op)->index());
917 42291386 : } else if (type == MachineType::Uint8() || type == MachineType::Uint16() ||
918 : type == MachineType::Uint32()) {
919 969 : translation->StoreUint32StackSlot(LocationOperand::cast(op)->index());
920 : } else {
921 14096166 : CHECK_EQ(MachineRepresentation::kTagged, type.representation());
922 14096166 : translation->StoreStackSlot(LocationOperand::cast(op)->index());
923 : }
924 7947474 : } else if (op->IsFPStackSlot()) {
925 188096 : if (type.representation() == MachineRepresentation::kFloat64) {
926 187771 : translation->StoreDoubleStackSlot(LocationOperand::cast(op)->index());
927 : } else {
928 325 : CHECK_EQ(MachineRepresentation::kFloat32, type.representation());
929 325 : translation->StoreFloatStackSlot(LocationOperand::cast(op)->index());
930 : }
931 7759378 : } else if (op->IsRegister()) {
932 : InstructionOperandConverter converter(this, instr);
933 2179034 : if (type.representation() == MachineRepresentation::kBit) {
934 2732 : translation->StoreBoolRegister(converter.ToRegister(op));
935 6527637 : } else if (type == MachineType::Int8() || type == MachineType::Int16() ||
936 : type == MachineType::Int32()) {
937 53795 : translation->StoreInt32Register(converter.ToRegister(op));
938 6367519 : } else if (type == MachineType::Uint8() || type == MachineType::Uint16() ||
939 : type == MachineType::Uint32()) {
940 1473 : translation->StoreUint32Register(converter.ToRegister(op));
941 : } else {
942 2121034 : CHECK_EQ(MachineRepresentation::kTagged, type.representation());
943 2121034 : translation->StoreRegister(converter.ToRegister(op));
944 : }
945 5580344 : } else if (op->IsFPRegister()) {
946 : InstructionOperandConverter converter(this, instr);
947 69134 : if (type.representation() == MachineRepresentation::kFloat64) {
948 68907 : translation->StoreDoubleRegister(converter.ToDoubleRegister(op));
949 : } else {
950 227 : CHECK_EQ(MachineRepresentation::kFloat32, type.representation());
951 227 : translation->StoreFloatRegister(converter.ToFloatRegister(op));
952 : }
953 : } else {
954 5511210 : CHECK(op->IsImmediate());
955 : InstructionOperandConverter converter(this, instr);
956 5511210 : Constant constant = converter.ToConstant(op);
957 : DeoptimizationLiteral literal;
958 5511216 : switch (constant.type()) {
959 : case Constant::kInt32:
960 11777 : if (type.representation() == MachineRepresentation::kTagged) {
961 : // When pointers are 4 bytes, we can use int32 constants to represent
962 : // Smis.
963 : DCHECK_EQ(4, kPointerSize);
964 12 : Smi* smi = reinterpret_cast<Smi*>(constant.ToInt32());
965 : DCHECK(smi->IsSmi());
966 6 : literal = DeoptimizationLiteral(smi->value());
967 11771 : } else if (type.representation() == MachineRepresentation::kBit) {
968 162 : if (constant.ToInt32() == 0) {
969 : literal =
970 48 : DeoptimizationLiteral(isolate()->factory()->false_value());
971 : } else {
972 : DCHECK_EQ(1, constant.ToInt32());
973 33 : literal = DeoptimizationLiteral(isolate()->factory()->true_value());
974 : }
975 : } else {
976 : // TODO(jarin,bmeurer): We currently pass in raw pointers to the
977 : // JSFunction::entry here. We should really consider fixing this.
978 : DCHECK(type == MachineType::Int32() ||
979 : type == MachineType::Uint32() ||
980 : type.representation() == MachineRepresentation::kWord32 ||
981 : type.representation() == MachineRepresentation::kNone);
982 : DCHECK(type.representation() != MachineRepresentation::kNone ||
983 : constant.ToInt32() == FrameStateDescriptor::kImpossibleValue);
984 11690 : if (type == MachineType::Uint32()) {
985 : literal = DeoptimizationLiteral(
986 1028 : static_cast<uint32_t>(constant.ToInt32()));
987 : } else {
988 22352 : literal = DeoptimizationLiteral(constant.ToInt32());
989 : }
990 : }
991 : break;
992 : case Constant::kInt64:
993 : // When pointers are 8 bytes, we can use int64 constants to represent
994 : // Smis.
995 : // TODO(jarin,bmeurer): We currently pass in raw pointers to the
996 : // JSFunction::entry here. We should really consider fixing this.
997 : DCHECK(type.representation() == MachineRepresentation::kWord64 ||
998 : type.representation() == MachineRepresentation::kTagged);
999 : DCHECK_EQ(8, kPointerSize);
1000 : {
1001 : Smi* smi = reinterpret_cast<Smi*>(constant.ToInt64());
1002 : DCHECK(smi->IsSmi());
1003 0 : literal = DeoptimizationLiteral(smi->value());
1004 : }
1005 0 : break;
1006 : case Constant::kFloat32:
1007 : DCHECK(type.representation() == MachineRepresentation::kFloat32 ||
1008 : type.representation() == MachineRepresentation::kTagged);
1009 50 : literal = DeoptimizationLiteral(constant.ToFloat32());
1010 25 : break;
1011 : case Constant::kFloat64:
1012 : DCHECK(type.representation() == MachineRepresentation::kFloat64 ||
1013 : type.representation() == MachineRepresentation::kTagged);
1014 724959 : literal = DeoptimizationLiteral(constant.ToFloat64().value());
1015 724959 : break;
1016 : case Constant::kHeapObject:
1017 : DCHECK_EQ(MachineRepresentation::kTagged, type.representation());
1018 4774455 : literal = DeoptimizationLiteral(constant.ToHeapObject());
1019 4774454 : break;
1020 : default:
1021 0 : UNREACHABLE();
1022 : }
1023 5511215 : if (literal.object().equals(info()->closure())) {
1024 2989488 : translation->StoreJSFrameFunction();
1025 : } else {
1026 2521727 : int literal_id = DefineDeoptimizationLiteral(literal);
1027 2521724 : translation->StoreLiteral(literal_id);
1028 : }
1029 : }
1030 22307624 : }
1031 :
1032 0 : void CodeGenerator::MarkLazyDeoptSite() {
1033 5467448 : last_lazy_deopt_pc_ = tasm()->pc_offset();
1034 0 : }
1035 :
1036 302295 : DeoptimizationExit* CodeGenerator::AddDeoptimizationExit(
1037 302293 : Instruction* instr, size_t frame_state_offset) {
1038 : int const deoptimization_id = BuildTranslation(
1039 302295 : instr, -1, frame_state_offset, OutputFrameStateCombine::Ignore());
1040 :
1041 : DeoptimizationExit* const exit = new (zone())
1042 604589 : DeoptimizationExit(deoptimization_id, current_source_position_);
1043 302296 : deoptimization_exits_.push_back(exit);
1044 302298 : return exit;
1045 : }
1046 :
1047 1291998 : OutOfLineCode::OutOfLineCode(CodeGenerator* gen)
1048 1291998 : : frame_(gen->frame()), tasm_(gen->tasm()), next_(gen->ools_) {
1049 645999 : gen->ools_ = this;
1050 645999 : }
1051 :
1052 0 : OutOfLineCode::~OutOfLineCode() {}
1053 :
1054 1242928 : Handle<Object> DeoptimizationLiteral::Reify(Isolate* isolate) const {
1055 1242928 : return object_.is_null() ? isolate->factory()->NewNumber(number_) : object_;
1056 : }
1057 :
1058 : } // namespace compiler
1059 : } // namespace internal
1060 : } // namespace v8
|