Line data Source code
1 : // Copyright 2012 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/full-codegen/full-codegen.h"
6 :
7 : #include "src/ast/ast-numbering.h"
8 : #include "src/ast/ast.h"
9 : #include "src/ast/prettyprinter.h"
10 : #include "src/ast/scopes.h"
11 : #include "src/code-factory.h"
12 : #include "src/codegen.h"
13 : #include "src/compilation-info.h"
14 : #include "src/compiler.h"
15 : #include "src/debug/debug.h"
16 : #include "src/debug/liveedit.h"
17 : #include "src/frames-inl.h"
18 : #include "src/globals.h"
19 : #include "src/isolate-inl.h"
20 : #include "src/macro-assembler-inl.h"
21 : #include "src/macro-assembler.h"
22 : #include "src/snapshot/snapshot.h"
23 : #include "src/tracing/trace-event.h"
24 :
25 : namespace v8 {
26 : namespace internal {
27 :
28 : #define __ ACCESS_MASM(masm())
29 :
30 1697684 : class FullCodegenCompilationJob final : public CompilationJob {
31 : public:
32 848845 : explicit FullCodegenCompilationJob(CompilationInfo* info)
33 848845 : : CompilationJob(info->isolate(), info, "Full-Codegen") {}
34 :
35 848839 : bool can_execute_on_background_thread() const override { return false; }
36 :
37 848836 : CompilationJob::Status PrepareJobImpl() final { return SUCCEEDED; }
38 :
39 848842 : CompilationJob::Status ExecuteJobImpl() final {
40 : DCHECK(ThreadId::Current().Equals(isolate()->thread_id()));
41 848842 : return FullCodeGenerator::MakeCode(info(), stack_limit()) ? SUCCEEDED
42 848842 : : FAILED;
43 : }
44 :
45 848835 : CompilationJob::Status FinalizeJobImpl() final { return SUCCEEDED; }
46 :
47 : private:
48 : DISALLOW_COPY_AND_ASSIGN(FullCodegenCompilationJob);
49 : };
50 :
51 1080619 : FullCodeGenerator::FullCodeGenerator(MacroAssembler* masm,
52 5403086 : CompilationInfo* info,
53 : uintptr_t stack_limit)
54 : : masm_(masm),
55 : info_(info),
56 : isolate_(info->isolate()),
57 : zone_(info->zone()),
58 1080619 : scope_(info->scope()),
59 : nesting_stack_(NULL),
60 : loop_depth_(0),
61 : operand_stack_depth_(0),
62 : globals_(NULL),
63 : context_(NULL),
64 : bailout_entries_(info->HasDeoptimizationSupport()
65 236543 : ? info->literal()->ast_node_count()
66 : : 0,
67 : info->zone()),
68 : back_edges_(2, info->zone()),
69 : source_position_table_builder_(info->zone(),
70 : info->SourcePositionRecordingMode()),
71 9725556 : ic_total_count_(0) {
72 : DCHECK(!info->IsStub());
73 : Initialize(stack_limit);
74 1080610 : }
75 :
76 : // static
77 848835 : CompilationJob* FullCodeGenerator::NewCompilationJob(CompilationInfo* info) {
78 1697673 : return new FullCodegenCompilationJob(info);
79 : }
80 :
81 : // static
82 231775 : bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
83 231775 : return MakeCode(info, info->isolate()->stack_guard()->real_climit());
84 : }
85 :
86 : // static
87 3241844 : bool FullCodeGenerator::MakeCode(CompilationInfo* info, uintptr_t stack_limit) {
88 1080616 : Isolate* isolate = info->isolate();
89 :
90 : DCHECK(!info->shared_info()->must_use_ignition_turbo());
91 : DCHECK(!FLAG_minimal);
92 : RuntimeCallTimerScope runtimeTimer(isolate,
93 1080614 : &RuntimeCallStats::CompileFullCode);
94 : TimerEventScope<TimerEventCompileFullCode> timer(info->isolate());
95 3241854 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileFullCode");
96 :
97 1080617 : Handle<Script> script = info->script();
98 2161229 : if (!script->IsUndefined(isolate) &&
99 : !script->source()->IsUndefined(isolate)) {
100 : int len = String::cast(script->source())->length();
101 1080616 : isolate->counters()->total_full_codegen_source_size()->Increment(len);
102 : }
103 1080614 : CodeGenerator::MakeCodePrologue(info, "full");
104 : const int kInitialBufferSize = 4 * KB;
105 : MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize,
106 1080616 : CodeObjectRequired::kYes);
107 1080619 : if (info->will_serialize()) masm.enable_serializer();
108 :
109 1080619 : FullCodeGenerator cgen(&masm, info, stack_limit);
110 1080611 : cgen.Generate();
111 1080612 : if (cgen.HasStackOverflow()) {
112 : DCHECK(!isolate->has_pending_exception());
113 : return false;
114 : }
115 1080606 : unsigned table_offset = cgen.EmitBackEdgeTable();
116 :
117 : Handle<Code> code =
118 1080607 : CodeGenerator::MakeCodeEpilogue(&masm, nullptr, info, masm.CodeObject());
119 1080612 : cgen.PopulateDeoptimizationData(code);
120 1080611 : cgen.PopulateTypeFeedbackInfo(code);
121 : code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
122 : code->set_has_reloc_info_for_serialization(info->will_serialize());
123 : code->set_allow_osr_at_loop_nesting_level(0);
124 : code->set_profiler_ticks(0);
125 : code->set_back_edge_table_offset(table_offset);
126 : Handle<ByteArray> source_positions =
127 : cgen.source_position_table_builder_.ToSourcePositionTable(
128 1080610 : isolate, Handle<AbstractCode>::cast(code));
129 1080608 : code->set_source_position_table(*source_positions);
130 1080609 : CodeGenerator::PrintCode(code, info);
131 : info->SetCode(code);
132 :
133 : #ifdef DEBUG
134 : // Check that no context-specific object has been embedded.
135 : code->VerifyEmbeddedObjects(Code::kNoContextSpecificPointers);
136 : #endif // DEBUG
137 1080608 : return true;
138 : }
139 :
140 :
141 2450682 : unsigned FullCodeGenerator::EmitBackEdgeTable() {
142 : // The back edge table consists of a length (in number of entries)
143 : // field, and then a sequence of entries. Each entry is a pair of AST id
144 : // and code-relative pc offset.
145 1080603 : masm()->Align(kPointerSize);
146 2161218 : unsigned offset = masm()->pc_offset();
147 1370079 : unsigned length = back_edges_.length();
148 1080609 : __ dd(length);
149 1177097 : for (unsigned i = 0; i < length; ++i) {
150 289470 : __ dd(back_edges_[i].id.ToInt());
151 192980 : __ dd(back_edges_[i].pc);
152 192980 : __ dd(back_edges_[i].loop_depth);
153 : }
154 1080607 : return offset;
155 : }
156 :
157 :
158 1317155 : void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
159 : // Fill in the deoptimization information.
160 : DCHECK(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
161 3241833 : if (!info_->HasDeoptimizationSupport()) return;
162 17077242 : int length = bailout_entries_.length();
163 : Handle<DeoptimizationOutputData> data =
164 236544 : DeoptimizationOutputData::New(isolate(), length, TENURED);
165 8656893 : for (int i = 0; i < length; i++) {
166 8420349 : data->SetAstId(i, bailout_entries_[i].id);
167 8420349 : data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
168 : }
169 236544 : code->set_deoptimization_data(*data);
170 : }
171 :
172 :
173 1080608 : void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
174 1080608 : Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo();
175 1080614 : info->set_ic_total_count(ic_total_count_);
176 : DCHECK(!isolate()->heap()->InNewSpace(*info));
177 1080614 : code->set_type_feedback_info(*info);
178 1080609 : }
179 :
180 :
181 144384 : bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime(
182 144384 : ObjectLiteral* expr) const {
183 144384 : return masm()->serializer_enabled() || !expr->IsFastCloningSupported();
184 : }
185 :
186 :
187 74125 : bool FullCodeGenerator::MustCreateArrayLiteralWithRuntime(
188 : ArrayLiteral* expr) const {
189 74125 : return !expr->IsFastCloningSupported();
190 : }
191 :
192 0 : void FullCodeGenerator::Initialize(uintptr_t stack_limit) {
193 : InitializeAstVisitor(stack_limit);
194 1080610 : masm_->set_emit_debug_code(FLAG_debug_code);
195 : masm_->set_predictable_code_size(true);
196 0 : }
197 :
198 4103114 : void FullCodeGenerator::PrepareForBailout(Expression* node,
199 : BailoutState state) {
200 18317217 : PrepareForBailoutForId(node->id(), state);
201 4103116 : }
202 :
203 5520108 : void FullCodeGenerator::CallIC(Handle<Code> code, TypeFeedbackId ast_id) {
204 2760054 : ic_total_count_++;
205 2760054 : __ Call(code, RelocInfo::CODE_TARGET, ast_id);
206 2760058 : }
207 :
208 6982308 : void FullCodeGenerator::CallLoadIC(FeedbackSlot slot, Handle<Object> name) {
209 : DCHECK(name->IsName());
210 3491154 : __ Move(LoadDescriptor::NameRegister(), name);
211 :
212 1745577 : EmitLoadSlot(LoadDescriptor::SlotRegister(), slot);
213 :
214 3491154 : Handle<Code> code = CodeFactory::LoadIC(isolate()).code();
215 1745577 : __ Call(code, RelocInfo::CODE_TARGET);
216 1745577 : RestoreContext();
217 1745577 : }
218 :
219 1159102 : void FullCodeGenerator::CallStoreIC(FeedbackSlot slot, Handle<Object> name,
220 3477306 : StoreICKind store_ic_kind) {
221 : DCHECK(name->IsName());
222 2318204 : __ Move(StoreDescriptor::NameRegister(), name);
223 :
224 : STATIC_ASSERT(!StoreDescriptor::kPassLastArgsOnStack ||
225 : StoreDescriptor::kStackArgumentsCount == 2);
226 : if (StoreDescriptor::kPassLastArgsOnStack) {
227 : __ Push(StoreDescriptor::ValueRegister());
228 : EmitPushSlot(slot);
229 : } else {
230 1159102 : EmitLoadSlot(StoreDescriptor::SlotRegister(), slot);
231 : }
232 :
233 : Handle<Code> code;
234 1159102 : switch (store_ic_kind) {
235 : case kStoreOwn:
236 : DCHECK_EQ(FeedbackSlotKind::kStoreOwnNamed,
237 : feedback_vector_spec()->GetKind(slot));
238 380208 : code = CodeFactory::StoreOwnIC(isolate()).code();
239 190104 : break;
240 : case kStoreGlobal:
241 : // Ensure that language mode is in sync with the IC slot kind.
242 : DCHECK_EQ(
243 : GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
244 : language_mode());
245 119746 : code = CodeFactory::StoreGlobalIC(isolate(), language_mode()).code();
246 59873 : break;
247 : case kStoreNamed:
248 : // Ensure that language mode is in sync with the IC slot kind.
249 : DCHECK_EQ(
250 : GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
251 : language_mode());
252 1818250 : code = CodeFactory::StoreIC(isolate(), language_mode()).code();
253 909125 : break;
254 : }
255 1159102 : __ Call(code, RelocInfo::CODE_TARGET);
256 1159102 : RestoreContext();
257 1159102 : }
258 :
259 613137 : void FullCodeGenerator::CallKeyedStoreIC(FeedbackSlot slot) {
260 : STATIC_ASSERT(!StoreDescriptor::kPassLastArgsOnStack ||
261 : StoreDescriptor::kStackArgumentsCount == 2);
262 : if (StoreDescriptor::kPassLastArgsOnStack) {
263 : __ Push(StoreDescriptor::ValueRegister());
264 : EmitPushSlot(slot);
265 : } else {
266 204379 : EmitLoadSlot(StoreDescriptor::SlotRegister(), slot);
267 : }
268 :
269 : // Ensure that language mode is in sync with the IC slot kind.
270 : DCHECK_EQ(GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
271 : language_mode());
272 : Handle<Code> code =
273 408758 : CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
274 204379 : __ Call(code, RelocInfo::CODE_TARGET);
275 204379 : RestoreContext();
276 204379 : }
277 :
278 1105372 : void FullCodeGenerator::RecordJSReturnSite(Call* call) {
279 : // We record the offset of the function return so we can rebuild the frame
280 : // if the function was inlined, i.e., this is the return address in the
281 : // inlined function's frame.
282 : //
283 : // The bailout state is ignored. We defensively set it to TOS_REGISTER, which
284 : // is the real state of the unoptimized code at the return site.
285 1105372 : PrepareForBailoutForId(call->ReturnId(), BailoutState::TOS_REGISTER);
286 : #ifdef DEBUG
287 : // In debug builds, mark the return so we can verify that this function
288 : // was called.
289 : DCHECK(!call->return_is_recorded_);
290 : call->return_is_recorded_ = true;
291 : #endif
292 1105379 : }
293 :
294 42334958 : void FullCodeGenerator::PrepareForBailoutForId(BailoutId id,
295 8420295 : BailoutState state) {
296 : // There's no need to prepare this code for bailouts from already optimized
297 : // code or code that can't be optimized.
298 118584579 : if (!info_->HasDeoptimizationSupport()) return;
299 : unsigned pc_and_state =
300 25260885 : BailoutStateField::encode(state) | PcField::encode(masm_->pc_offset());
301 : DCHECK(Smi::IsValid(pc_and_state));
302 : #ifdef DEBUG
303 : for (int i = 0; i < bailout_entries_.length(); ++i) {
304 : DCHECK(bailout_entries_[i].id != id);
305 : }
306 : #endif
307 8420295 : BailoutEntry entry = { id, pc_and_state };
308 : bailout_entries_.Add(entry, zone());
309 : }
310 :
311 :
312 192980 : void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) {
313 : // The pc offset does not need to be encoded and packed together with a state.
314 : DCHECK(masm_->pc_offset() > 0);
315 : DCHECK(loop_depth() > 0);
316 : uint8_t depth = Min(loop_depth(), AbstractCode::kMaxLoopNestingMarker);
317 : BackEdgeEntry entry =
318 192980 : { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth };
319 : back_edges_.Add(entry, zone());
320 96490 : }
321 :
322 :
323 656293 : bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
324 : // Inline smi case inside loops, but not division and modulo which
325 : // are too complicated and take up too much space.
326 1299194 : if (op == Token::DIV ||op == Token::MOD) return false;
327 1256885 : if (FLAG_always_inline_smi_code) return true;
328 1254605 : return loop_depth_ > 0;
329 : }
330 :
331 :
332 2340 : void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
333 : DCHECK(var->IsStackAllocated() || var->IsContextSlot());
334 2340 : }
335 :
336 :
337 2542424 : void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
338 : DCHECK(var->IsStackAllocated() || var->IsContextSlot());
339 2542424 : codegen()->GetVar(result_register(), var);
340 2542433 : }
341 :
342 :
343 149954 : void FullCodeGenerator::TestContext::Plug(Variable* var) const {
344 : DCHECK(var->IsStackAllocated() || var->IsContextSlot());
345 : // For simplicity we always test the accumulator register.
346 224931 : codegen()->GetVar(result_register(), var);
347 74977 : codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
348 : codegen()->DoTest(this);
349 74977 : }
350 :
351 :
352 2945955 : void FullCodeGenerator::EffectContext::Plug(Register reg) const {
353 2945955 : }
354 :
355 :
356 2590830 : void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
357 2590830 : __ Move(result_register(), reg);
358 2590833 : }
359 :
360 :
361 2211038 : void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
362 2211038 : codegen()->PushOperand(reg);
363 2211039 : }
364 :
365 :
366 91684 : void FullCodeGenerator::TestContext::Plug(Register reg) const {
367 : // For simplicity we always test the accumulator register.
368 137526 : __ Move(result_register(), reg);
369 45842 : codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
370 : codegen()->DoTest(this);
371 45842 : }
372 :
373 :
374 35 : void FullCodeGenerator::EffectContext::Plug(bool flag) const {}
375 :
376 466950 : void FullCodeGenerator::EffectContext::DropAndPlug(int count,
377 : Register reg) const {
378 : DCHECK(count > 0);
379 466950 : codegen()->DropOperands(count);
380 466950 : }
381 :
382 427232 : void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
383 : int count, Register reg) const {
384 : DCHECK(count > 0);
385 854473 : codegen()->DropOperands(count);
386 854482 : __ Move(result_register(), reg);
387 427241 : }
388 :
389 61012 : void FullCodeGenerator::TestContext::DropAndPlug(int count,
390 61012 : Register reg) const {
391 : DCHECK(count > 0);
392 : // For simplicity we always test the accumulator register.
393 244048 : codegen()->DropOperands(count);
394 122024 : __ Move(result_register(), reg);
395 61012 : codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
396 : codegen()->DoTest(this);
397 61012 : }
398 :
399 71 : void FullCodeGenerator::EffectContext::PlugTOS() const {
400 71 : codegen()->DropOperands(1);
401 71 : }
402 :
403 :
404 62450 : void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
405 62450 : codegen()->PopOperand(result_register());
406 62450 : }
407 :
408 :
409 36293 : void FullCodeGenerator::StackValueContext::PlugTOS() const {
410 36293 : }
411 :
412 :
413 14046 : void FullCodeGenerator::TestContext::PlugTOS() const {
414 : // For simplicity we always test the accumulator register.
415 21069 : codegen()->PopOperand(result_register());
416 7023 : codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
417 : codegen()->DoTest(this);
418 7023 : }
419 :
420 :
421 123 : void FullCodeGenerator::EffectContext::PrepareTest(
422 : Label* materialize_true,
423 : Label* materialize_false,
424 : Label** if_true,
425 : Label** if_false,
426 : Label** fall_through) const {
427 : // In an effect context, the true and the false case branch to the
428 : // same label.
429 123 : *if_true = *if_false = *fall_through = materialize_true;
430 123 : }
431 :
432 :
433 54288 : void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
434 : Label* materialize_true,
435 : Label* materialize_false,
436 : Label** if_true,
437 : Label** if_false,
438 : Label** fall_through) const {
439 54288 : *if_true = *fall_through = materialize_true;
440 54288 : *if_false = materialize_false;
441 54288 : }
442 :
443 :
444 6586 : void FullCodeGenerator::StackValueContext::PrepareTest(
445 : Label* materialize_true,
446 : Label* materialize_false,
447 : Label** if_true,
448 : Label** if_false,
449 : Label** fall_through) const {
450 6586 : *if_true = *fall_through = materialize_true;
451 6586 : *if_false = materialize_false;
452 6586 : }
453 :
454 :
455 518828 : void FullCodeGenerator::TestContext::PrepareTest(
456 : Label* materialize_true,
457 : Label* materialize_false,
458 : Label** if_true,
459 : Label** if_false,
460 : Label** fall_through) const {
461 518828 : *if_true = true_label_;
462 518828 : *if_false = false_label_;
463 518828 : *fall_through = fall_through_;
464 518828 : }
465 :
466 :
467 188858 : void FullCodeGenerator::DoTest(const TestContext* context) {
468 : DoTest(context->condition(),
469 : context->true_label(),
470 : context->false_label(),
471 188858 : context->fall_through());
472 4 : }
473 :
474 2292377 : void FullCodeGenerator::VisitDeclarations(Declaration::List* declarations) {
475 1126560 : ZoneList<Handle<Object> >* saved_globals = globals_;
476 1126560 : ZoneList<Handle<Object> > inner_globals(10, zone());
477 1126572 : globals_ = &inner_globals;
478 :
479 : AstVisitor<FullCodeGenerator>::VisitDeclarations(declarations);
480 :
481 2958049 : if (!globals_->is_empty()) {
482 : // Invoke the platform-dependent code generator to do the actual
483 : // declaration of the global functions and variables.
484 : Handle<FixedArray> array =
485 39257 : isolate()->factory()->NewFixedArray(globals_->length(), TENURED);
486 3662954 : for (int i = 0; i < globals_->length(); ++i)
487 1792220 : array->set(i, *globals_->at(i));
488 39257 : DeclareGlobals(array);
489 : }
490 :
491 1126572 : globals_ = saved_globals;
492 1126572 : }
493 :
494 :
495 0 : void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
496 : Comment cmnt(masm_, "[ VariableProxy");
497 5655445 : EmitVariableLoad(expr);
498 0 : }
499 :
500 814565 : void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
501 2443693 : TypeofMode typeof_mode) {
502 814565 : Variable* var = proxy->var();
503 : DCHECK(var->IsUnallocated());
504 1629129 : __ Move(LoadDescriptor::NameRegister(), var->name());
505 :
506 : FeedbackSlot slot = proxy->VariableFeedbackSlot();
507 : // Ensure that typeof mode is in sync with the IC slot kind.
508 : DCHECK_EQ(GetTypeofModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
509 : typeof_mode);
510 :
511 : EmitLoadSlot(LoadGlobalDescriptor::SlotRegister(), slot);
512 1629129 : Handle<Code> code = CodeFactory::LoadGlobalIC(isolate(), typeof_mode).code();
513 814564 : __ Call(code, RelocInfo::CODE_TARGET);
514 814565 : RestoreContext();
515 814565 : }
516 :
517 1142 : void FullCodeGenerator::VisitSloppyBlockFunctionStatement(
518 1142 : SloppyBlockFunctionStatement* declaration) {
519 1142 : Visit(declaration->statement());
520 1142 : }
521 :
522 :
523 39257 : int FullCodeGenerator::DeclareGlobalsFlags() {
524 39257 : return info_->GetDeclareGlobalsFlags();
525 : }
526 :
527 639878 : void FullCodeGenerator::PushOperand(Handle<Object> handle) {
528 : OperandStackDepthIncrement(1);
529 322243 : __ Push(handle);
530 317635 : }
531 :
532 16092 : void FullCodeGenerator::PushOperand(Smi* smi) {
533 : OperandStackDepthIncrement(1);
534 8046 : __ Push(smi);
535 8046 : }
536 :
537 2569516 : void FullCodeGenerator::PushOperand(Register reg) {
538 : OperandStackDepthIncrement(1);
539 2390277 : __ Push(reg);
540 179239 : }
541 :
542 4664219 : void FullCodeGenerator::PopOperand(Register reg) {
543 : OperandStackDepthDecrement(1);
544 2475646 : __ Pop(reg);
545 2188573 : }
546 :
547 983751 : void FullCodeGenerator::DropOperands(int count) {
548 : OperandStackDepthDecrement(count);
549 969508 : __ Drop(count);
550 14243 : }
551 :
552 94958 : void FullCodeGenerator::CallRuntimeWithOperands(Runtime::FunctionId id) {
553 47479 : OperandStackDepthDecrement(Runtime::FunctionForId(id)->nargs);
554 47479 : __ CallRuntime(id);
555 47479 : }
556 :
557 5056803 : void FullCodeGenerator::OperandStackDepthIncrement(int count) {
558 : DCHECK_IMPLIES(!HasStackOverflow(), operand_stack_depth_ >= 0);
559 : DCHECK_GE(count, 0);
560 8067727 : operand_stack_depth_ += count;
561 5056803 : }
562 :
563 1273489 : void FullCodeGenerator::OperandStackDepthDecrement(int count) {
564 : DCHECK_IMPLIES(!HasStackOverflow(), operand_stack_depth_ >= count);
565 : DCHECK_GE(count, 0);
566 4975143 : operand_stack_depth_ -= count;
567 1273489 : }
568 :
569 1592 : void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
570 : // Load the arguments on the stack and call the stub.
571 : SubStringStub stub(isolate());
572 : ZoneList<Expression*>* args = expr->arguments();
573 : DCHECK(args->length() == 3);
574 398 : VisitForStackValue(args->at(0));
575 398 : VisitForStackValue(args->at(1));
576 398 : VisitForStackValue(args->at(2));
577 398 : __ CallStub(&stub);
578 398 : RestoreContext();
579 : OperandStackDepthDecrement(3);
580 398 : context()->Plug(result_register());
581 398 : }
582 :
583 :
584 11214 : void FullCodeGenerator::EmitIntrinsicAsStubCall(CallRuntime* expr,
585 33642 : const Callable& callable) {
586 : ZoneList<Expression*>* args = expr->arguments();
587 : int param_count = callable.descriptor().GetRegisterParameterCount();
588 : DCHECK_EQ(args->length(), param_count);
589 :
590 11214 : if (param_count > 0) {
591 11214 : int last = param_count - 1;
592 : // Put all but last arguments on stack.
593 11214 : for (int i = 0; i < last; i++) {
594 0 : VisitForStackValue(args->at(i));
595 : }
596 : // The last argument goes to the accumulator.
597 11214 : VisitForAccumulatorValue(args->at(last));
598 :
599 : // Move the arguments to the registers, as required by the stub.
600 : __ Move(callable.descriptor().GetRegisterParameter(last),
601 22428 : result_register());
602 22428 : for (int i = last; i-- > 0;) {
603 : PopOperand(callable.descriptor().GetRegisterParameter(i));
604 : }
605 : }
606 11214 : __ Call(callable.code(), RelocInfo::CODE_TARGET);
607 :
608 : // Reload the context register after the call as i.e. TurboFan code stubs
609 : // won't preserve the context register.
610 : LoadFromFrameField(StandardFrameConstants::kContextOffset,
611 11214 : context_register());
612 11214 : context()->Plug(result_register());
613 11214 : }
614 :
615 :
616 5564 : void FullCodeGenerator::EmitToString(CallRuntime* expr) {
617 5564 : EmitIntrinsicAsStubCall(expr, CodeFactory::ToString(isolate()));
618 5564 : }
619 :
620 :
621 1796 : void FullCodeGenerator::EmitToLength(CallRuntime* expr) {
622 1796 : EmitIntrinsicAsStubCall(expr, CodeFactory::ToLength(isolate()));
623 1796 : }
624 :
625 1427 : void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
626 1427 : EmitIntrinsicAsStubCall(expr, CodeFactory::ToInteger(isolate()));
627 1427 : }
628 :
629 324 : void FullCodeGenerator::EmitToNumber(CallRuntime* expr) {
630 324 : EmitIntrinsicAsStubCall(expr, CodeFactory::ToNumber(isolate()));
631 324 : }
632 :
633 :
634 2103 : void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
635 2103 : EmitIntrinsicAsStubCall(expr, CodeFactory::ToObject(isolate()));
636 2103 : }
637 :
638 :
639 12668 : void FullCodeGenerator::EmitHasProperty() {
640 6334 : Callable callable = CodeFactory::HasProperty(isolate());
641 : PopOperand(callable.descriptor().GetRegisterParameter(1));
642 : PopOperand(callable.descriptor().GetRegisterParameter(0));
643 6334 : __ Call(callable.code(), RelocInfo::CODE_TARGET);
644 6334 : RestoreContext();
645 6334 : }
646 :
647 6365048 : void FullCodeGenerator::RecordStatementPosition(int pos) {
648 : DCHECK_NE(kNoSourcePosition, pos);
649 6365048 : source_position_table_builder_.AddPosition(masm_->pc_offset(),
650 6365048 : SourcePosition(pos), true);
651 6365071 : }
652 :
653 14965087 : void FullCodeGenerator::RecordPosition(int pos) {
654 : DCHECK_NE(kNoSourcePosition, pos);
655 14965087 : source_position_table_builder_.AddPosition(masm_->pc_offset(),
656 14965087 : SourcePosition(pos), false);
657 14965105 : }
658 :
659 :
660 1080604 : void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
661 1080604 : RecordPosition(fun->start_position());
662 1080618 : }
663 :
664 :
665 1080615 : void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
666 : // For default constructors, start position equals end position, and there
667 : // is no source code besides the class literal.
668 1080615 : RecordStatementPosition(fun->return_position());
669 1080621 : if (info_->is_debug()) {
670 : // Always emit a debug break slot before a return.
671 3435 : DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
672 : }
673 1080620 : }
674 :
675 :
676 5801718 : void FullCodeGenerator::SetStatementPosition(
677 : Statement* stmt, FullCodeGenerator::InsertBreak insert_break) {
678 11603443 : if (stmt->position() == kNoSourcePosition) return;
679 5196383 : RecordStatementPosition(stmt->position());
680 5206950 : if (insert_break == INSERT_BREAK && info_->is_debug() &&
681 : !stmt->IsDebuggerStatement()) {
682 10560 : DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
683 : }
684 : }
685 :
686 9502935 : void FullCodeGenerator::SetExpressionPosition(Expression* expr) {
687 23244376 : if (expr->position() == kNoSourcePosition) return;
688 12634360 : RecordPosition(expr->position());
689 : }
690 :
691 :
692 92959 : void FullCodeGenerator::SetExpressionAsStatementPosition(Expression* expr) {
693 185918 : if (expr->position() == kNoSourcePosition) return;
694 88062 : RecordStatementPosition(expr->position());
695 88062 : if (info_->is_debug()) {
696 74 : DebugCodegen::GenerateSlot(masm_, RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
697 : }
698 : }
699 :
700 1250135 : void FullCodeGenerator::SetCallPosition(Expression* expr,
701 : TailCallMode tail_call_mode) {
702 2500271 : if (expr->position() == kNoSourcePosition) return;
703 1250140 : RecordPosition(expr->position());
704 1250142 : if (info_->is_debug()) {
705 : RelocInfo::Mode mode = (tail_call_mode == TailCallMode::kAllow)
706 : ? RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL
707 2959 : : RelocInfo::DEBUG_BREAK_SLOT_AT_CALL;
708 : // Always emit a debug break slot before a call.
709 2959 : DebugCodegen::GenerateSlot(masm_, mode);
710 : }
711 : }
712 :
713 :
714 0 : void FullCodeGenerator::VisitSuperPropertyReference(
715 0 : SuperPropertyReference* super) {
716 0 : __ CallRuntime(Runtime::kThrowUnsupportedSuperError);
717 : // Even though this expression doesn't produce a value, we need to simulate
718 : // plugging of the value context to ensure stack depth tracking is in sync.
719 0 : if (context()->IsStackValue()) OperandStackDepthIncrement(1);
720 0 : }
721 :
722 :
723 0 : void FullCodeGenerator::VisitSuperCallReference(SuperCallReference* super) {
724 : // Handled by VisitCall
725 0 : UNREACHABLE();
726 : }
727 :
728 :
729 0 : void FullCodeGenerator::EmitDebugBreakInOptimizedCode(CallRuntime* expr) {
730 0 : context()->Plug(handle(Smi::kZero, isolate()));
731 0 : }
732 :
733 :
734 813522 : void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
735 813522 : switch (expr->op()) {
736 : case Token::COMMA:
737 23069 : return VisitComma(expr);
738 : case Token::OR:
739 : case Token::AND:
740 147552 : return VisitLogicalExpression(expr);
741 : default:
742 642901 : return VisitArithmeticExpression(expr);
743 : }
744 : }
745 :
746 :
747 925293 : void FullCodeGenerator::VisitInDuplicateContext(Expression* expr) {
748 299592 : if (context()->IsEffect()) {
749 7511 : VisitForEffect(expr);
750 292081 : } else if (context()->IsAccumulatorValue()) {
751 169529 : VisitForAccumulatorValue(expr);
752 122552 : } else if (context()->IsStackValue()) {
753 17018 : VisitForStackValue(expr);
754 105534 : } else if (context()->IsTest()) {
755 105534 : const TestContext* test = TestContext::cast(context());
756 : VisitForControl(expr, test->true_label(), test->false_label(),
757 105534 : test->fall_through());
758 : }
759 299592 : }
760 :
761 :
762 46138 : void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
763 : Comment cmnt(masm_, "[ Comma");
764 23069 : VisitForEffect(expr->left());
765 23069 : VisitInDuplicateContext(expr->right());
766 23069 : }
767 :
768 :
769 1091443 : void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
770 147552 : bool is_logical_and = expr->op() == Token::AND;
771 : Comment cmnt(masm_, is_logical_and ? "[ Logical AND" : "[ Logical OR");
772 : Expression* left = expr->left();
773 : Expression* right = expr->right();
774 147552 : BailoutId right_id = expr->RightId();
775 : Label done;
776 :
777 147552 : if (context()->IsTest()) {
778 : Label eval_right;
779 104673 : const TestContext* test = TestContext::cast(context());
780 104673 : if (is_logical_and) {
781 39592 : VisitForControl(left, &eval_right, test->false_label(), &eval_right);
782 : } else {
783 65081 : VisitForControl(left, test->true_label(), &eval_right, &eval_right);
784 : }
785 104673 : PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
786 104673 : __ bind(&eval_right);
787 :
788 42879 : } else if (context()->IsAccumulatorValue()) {
789 38775 : VisitForAccumulatorValue(left);
790 : // We want the value in the accumulator for the test, and on the stack in
791 : // case we need it.
792 77550 : __ Push(result_register());
793 : Label discard, restore;
794 38775 : if (is_logical_and) {
795 22769 : DoTest(left, &discard, &restore, &restore);
796 : } else {
797 16006 : DoTest(left, &restore, &discard, &restore);
798 : }
799 38775 : __ bind(&restore);
800 77550 : __ Pop(result_register());
801 38775 : __ jmp(&done);
802 38775 : __ bind(&discard);
803 38775 : __ Drop(1);
804 38775 : PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
805 :
806 4104 : } else if (context()->IsStackValue()) {
807 4076 : VisitForAccumulatorValue(left);
808 : // We want the value in the accumulator for the test, and on the stack in
809 : // case we need it.
810 8152 : __ Push(result_register());
811 : Label discard;
812 4076 : if (is_logical_and) {
813 188 : DoTest(left, &discard, &done, &discard);
814 : } else {
815 3888 : DoTest(left, &done, &discard, &discard);
816 : }
817 4076 : __ bind(&discard);
818 4076 : __ Drop(1);
819 4076 : PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
820 :
821 : } else {
822 : DCHECK(context()->IsEffect());
823 : Label eval_right;
824 28 : if (is_logical_and) {
825 24 : VisitForControl(left, &eval_right, &done, &eval_right);
826 : } else {
827 4 : VisitForControl(left, &done, &eval_right, &eval_right);
828 : }
829 28 : PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
830 28 : __ bind(&eval_right);
831 : }
832 :
833 147552 : VisitInDuplicateContext(right);
834 147552 : __ bind(&done);
835 147552 : }
836 :
837 :
838 1285802 : void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
839 : Token::Value op = expr->op();
840 : Comment cmnt(masm_, "[ ArithmeticExpression");
841 : Expression* left = expr->left();
842 : Expression* right = expr->right();
843 :
844 642901 : VisitForStackValue(left);
845 642901 : VisitForAccumulatorValue(right);
846 :
847 : SetExpressionPosition(expr);
848 642901 : if (ShouldInlineSmiCase(op)) {
849 214288 : EmitInlineSmiBinaryOp(expr, op, left, right);
850 : } else {
851 428613 : EmitBinaryOp(expr, op);
852 : }
853 642901 : }
854 :
855 7459157 : void FullCodeGenerator::VisitProperty(Property* expr) {
856 : Comment cmnt(masm_, "[ Property");
857 : SetExpressionPosition(expr);
858 :
859 : Expression* key = expr->key();
860 :
861 1450845 : if (key->IsPropertyName()) {
862 : DCHECK(!expr->IsSuperAccess());
863 1245913 : VisitForAccumulatorValue(expr->obj());
864 2491826 : __ Move(LoadDescriptor::ReceiverRegister(), result_register());
865 1245913 : EmitNamedPropertyLoad(expr);
866 : } else {
867 : DCHECK(!expr->IsSuperAccess());
868 204932 : VisitForStackValue(expr->obj());
869 204932 : VisitForAccumulatorValue(expr->key());
870 409864 : __ Move(LoadDescriptor::NameRegister(), result_register());
871 204932 : PopOperand(LoadDescriptor::ReceiverRegister());
872 204932 : EmitKeyedPropertyLoad(expr);
873 : }
874 1450845 : PrepareForBailoutForId(expr->LoadId(), BailoutState::TOS_REGISTER);
875 1450845 : context()->Plug(result_register());
876 1450845 : }
877 :
878 84209 : void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
879 164888 : VariableProxy* proxy = expr->AsVariableProxy();
880 : DCHECK(!context()->IsEffect());
881 : DCHECK(!context()->IsTest());
882 :
883 164888 : if (proxy != NULL && proxy->var()->IsUnallocated()) {
884 272 : EmitVariableLoad(proxy, INSIDE_TYPEOF);
885 : PrepareForBailout(proxy, BailoutState::TOS_REGISTER);
886 : } else {
887 : // This expression cannot throw a reference error at the top level.
888 83937 : VisitInDuplicateContext(expr);
889 : }
890 84209 : }
891 :
892 :
893 5957024 : void FullCodeGenerator::VisitBlock(Block* stmt) {
894 : Comment cmnt(masm_, "[ Block");
895 : NestedBlock nested_block(this, stmt);
896 :
897 : {
898 : EnterBlockScopeIfNeeded block_scope_state(
899 1985675 : this, stmt->scope(), stmt->EntryId(), stmt->DeclsId(), stmt->ExitId());
900 1985675 : VisitStatements(stmt->statements());
901 1985674 : __ bind(nested_block.break_label());
902 : }
903 1985675 : }
904 :
905 :
906 528 : void FullCodeGenerator::VisitDoExpression(DoExpression* expr) {
907 : Comment cmnt(masm_, "[ Do Expression");
908 : SetExpressionPosition(expr);
909 176 : VisitBlock(expr->block());
910 176 : VisitInDuplicateContext(expr->result());
911 176 : }
912 :
913 :
914 7976897 : void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
915 : Comment cmnt(masm_, "[ ExpressionStatement");
916 3988447 : SetStatementPosition(stmt);
917 3988450 : VisitForEffect(stmt->expression());
918 3988446 : }
919 :
920 :
921 8 : void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
922 : Comment cmnt(masm_, "[ EmptyStatement");
923 8 : }
924 :
925 :
926 2720509 : void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
927 : Comment cmnt(masm_, "[ IfStatement");
928 494672 : SetStatementPosition(stmt);
929 : Label then_part, else_part, done;
930 :
931 494672 : if (stmt->HasElseStatement()) {
932 82383 : VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
933 82383 : PrepareForBailoutForId(stmt->ThenId(), BailoutState::NO_REGISTERS);
934 82383 : __ bind(&then_part);
935 82383 : Visit(stmt->then_statement());
936 82383 : __ jmp(&done);
937 :
938 82383 : PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS);
939 82383 : __ bind(&else_part);
940 82383 : Visit(stmt->else_statement());
941 : } else {
942 412289 : VisitForControl(stmt->condition(), &then_part, &done, &then_part);
943 412289 : PrepareForBailoutForId(stmt->ThenId(), BailoutState::NO_REGISTERS);
944 412289 : __ bind(&then_part);
945 412289 : Visit(stmt->then_statement());
946 :
947 412289 : PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS);
948 : }
949 494672 : __ bind(&done);
950 494672 : PrepareForBailoutForId(stmt->IfId(), BailoutState::NO_REGISTERS);
951 494672 : }
952 :
953 18877 : void FullCodeGenerator::EmitContinue(Statement* target) {
954 7610 : NestedStatement* current = nesting_stack_;
955 3805 : int context_length = 0;
956 : // When continuing, we clobber the unpredictable value in the accumulator
957 : // with one that's safe for GC.
958 3805 : ClearAccumulator();
959 15072 : while (!current->IsContinueTarget(target)) {
960 7462 : if (HasStackOverflow()) return;
961 7462 : current = current->Exit(&context_length);
962 : }
963 : int stack_depth = current->GetStackDepthAtTarget();
964 3805 : int stack_drop = operand_stack_depth_ - stack_depth;
965 : DCHECK_GE(stack_drop, 0);
966 3805 : __ Drop(stack_drop);
967 3805 : if (context_length > 0) {
968 0 : while (context_length > 0) {
969 0 : LoadContextField(context_register(), Context::PREVIOUS_INDEX);
970 0 : --context_length;
971 : }
972 : StoreToFrameField(StandardFrameConstants::kContextOffset,
973 0 : context_register());
974 : }
975 :
976 7610 : __ jmp(current->AsIteration()->continue_label());
977 : }
978 :
979 7610 : void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
980 : Comment cmnt(masm_, "[ ContinueStatement");
981 3805 : SetStatementPosition(stmt);
982 3805 : EmitContinue(stmt->target());
983 3805 : }
984 :
985 164998 : void FullCodeGenerator::EmitBreak(Statement* target) {
986 80594 : NestedStatement* current = nesting_stack_;
987 40297 : int context_length = 0;
988 : // When breaking, we clobber the unpredictable value in the accumulator
989 : // with one that's safe for GC.
990 40297 : ClearAccumulator();
991 124701 : while (!current->IsBreakTarget(target)) {
992 44107 : if (HasStackOverflow()) return;
993 44107 : current = current->Exit(&context_length);
994 : }
995 : int stack_depth = current->GetStackDepthAtTarget();
996 40297 : int stack_drop = operand_stack_depth_ - stack_depth;
997 : DCHECK_GE(stack_drop, 0);
998 40297 : __ Drop(stack_drop);
999 40297 : if (context_length > 0) {
1000 4908 : while (context_length > 0) {
1001 2454 : LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1002 2454 : --context_length;
1003 : }
1004 : StoreToFrameField(StandardFrameConstants::kContextOffset,
1005 2454 : context_register());
1006 : }
1007 :
1008 80594 : __ jmp(current->AsBreakable()->break_label());
1009 : }
1010 :
1011 80594 : void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
1012 : Comment cmnt(masm_, "[ BreakStatement");
1013 40297 : SetStatementPosition(stmt);
1014 40297 : EmitBreak(stmt->target());
1015 40297 : }
1016 :
1017 1355463 : void FullCodeGenerator::EmitUnwindAndReturn() {
1018 1113493 : NestedStatement* current = nesting_stack_;
1019 1113493 : int context_length = 0;
1020 2468956 : while (current != NULL) {
1021 241970 : if (HasStackOverflow()) return;
1022 241970 : current = current->Exit(&context_length);
1023 : }
1024 1113493 : EmitReturnSequence();
1025 : }
1026 :
1027 1343927 : void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
1028 8265553 : FeedbackSlot slot, bool pretenure) {
1029 : // If slot is invalid, then it's a native function literal and we
1030 : // can pass the empty array or empty literal array, something like that...
1031 :
1032 : // If we're running with the --always-opt or the --prepare-always-opt
1033 : // flag, we need to use the runtime function so that the new function
1034 : // we are creating here gets a chance to have its code optimized and
1035 : // doesn't just get a copy of the existing unoptimized code.
1036 1545920 : if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure &&
1037 201993 : scope()->is_function_scope()) {
1038 93791 : Callable callable = CodeFactory::FastNewClosure(isolate());
1039 93791 : __ Move(callable.descriptor().GetRegisterParameter(0), info);
1040 93791 : __ EmitLoadFeedbackVector(callable.descriptor().GetRegisterParameter(1));
1041 : __ Move(callable.descriptor().GetRegisterParameter(2), SmiFromSlot(slot));
1042 93791 : __ Call(callable.code(), RelocInfo::CODE_TARGET);
1043 : } else {
1044 1250136 : __ Push(info);
1045 2500277 : __ EmitLoadFeedbackVector(result_register());
1046 2500277 : __ Push(result_register());
1047 1250137 : __ Push(SmiFromSlot(slot));
1048 : __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured
1049 2500256 : : Runtime::kNewClosure);
1050 : }
1051 1343926 : context()->Plug(result_register());
1052 1343928 : }
1053 :
1054 3491153 : void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
1055 : SetExpressionPosition(prop);
1056 3491154 : Literal* key = prop->key()->AsLiteral();
1057 : DCHECK(!key->value()->IsSmi());
1058 : DCHECK(!prop->IsSuperAccess());
1059 :
1060 1745577 : CallLoadIC(prop->PropertyFeedbackSlot(), key->value());
1061 1745577 : }
1062 :
1063 622923 : void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1064 : SetExpressionPosition(prop);
1065 :
1066 207641 : EmitLoadSlot(LoadDescriptor::SlotRegister(), prop->PropertyFeedbackSlot());
1067 :
1068 415282 : Handle<Code> code = CodeFactory::KeyedLoadIC(isolate()).code();
1069 207641 : __ Call(code, RelocInfo::CODE_TARGET);
1070 207641 : RestoreContext();
1071 207641 : }
1072 :
1073 4131263 : void FullCodeGenerator::EmitLoadSlot(Register destination, FeedbackSlot slot) {
1074 : DCHECK(!slot.IsInvalid());
1075 : __ Move(destination, SmiFromSlot(slot));
1076 0 : }
1077 :
1078 0 : void FullCodeGenerator::EmitPushSlot(FeedbackSlot slot) {
1079 0 : __ Push(SmiFromSlot(slot));
1080 0 : }
1081 :
1082 2226999 : void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
1083 : Comment cmnt(masm_, "[ ReturnStatement");
1084 1113496 : SetStatementPosition(stmt);
1085 : Expression* expr = stmt->expression();
1086 1113503 : VisitForAccumulatorValue(expr);
1087 1113502 : EmitUnwindAndReturn();
1088 1113498 : }
1089 :
1090 :
1091 0 : void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
1092 : // Dynamic scoping is not supported.
1093 0 : UNREACHABLE();
1094 : }
1095 :
1096 :
1097 26440 : void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
1098 : Comment cmnt(masm_, "[ DoWhileStatement");
1099 : // Do not insert break location as we do that below.
1100 3305 : SetStatementPosition(stmt, SKIP_BREAK);
1101 :
1102 : Label body, book_keeping;
1103 :
1104 : Iteration loop_statement(this, stmt);
1105 : increment_loop_depth();
1106 :
1107 3305 : __ bind(&body);
1108 3305 : Visit(stmt->body());
1109 :
1110 : // Record the position of the do while condition and make sure it is
1111 : // possible to break on the condition.
1112 3305 : __ bind(loop_statement.continue_label());
1113 3305 : PrepareForBailoutForId(stmt->ContinueId(), BailoutState::NO_REGISTERS);
1114 :
1115 : // Here is the actual 'while' keyword.
1116 3305 : SetExpressionAsStatementPosition(stmt->cond());
1117 : VisitForControl(stmt->cond(),
1118 : &book_keeping,
1119 : loop_statement.break_label(),
1120 3305 : &book_keeping);
1121 :
1122 : // Check stack before looping.
1123 3305 : PrepareForBailoutForId(stmt->BackEdgeId(), BailoutState::NO_REGISTERS);
1124 3305 : __ bind(&book_keeping);
1125 3305 : EmitBackEdgeBookkeeping(stmt, &body);
1126 3305 : __ jmp(&body);
1127 :
1128 3305 : PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
1129 3305 : __ bind(loop_statement.break_label());
1130 : decrement_loop_depth();
1131 3305 : }
1132 :
1133 :
1134 89272 : void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1135 : Comment cmnt(masm_, "[ WhileStatement");
1136 : Label loop, body;
1137 :
1138 : Iteration loop_statement(this, stmt);
1139 : increment_loop_depth();
1140 :
1141 11159 : __ bind(&loop);
1142 :
1143 11159 : SetExpressionAsStatementPosition(stmt->cond());
1144 : VisitForControl(stmt->cond(),
1145 : &body,
1146 : loop_statement.break_label(),
1147 11159 : &body);
1148 :
1149 11159 : PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
1150 11159 : __ bind(&body);
1151 11159 : Visit(stmt->body());
1152 :
1153 11159 : __ bind(loop_statement.continue_label());
1154 :
1155 : // Check stack before looping.
1156 11159 : EmitBackEdgeBookkeeping(stmt, &loop);
1157 11159 : __ jmp(&loop);
1158 :
1159 11159 : PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
1160 11159 : __ bind(loop_statement.break_label());
1161 : decrement_loop_depth();
1162 11159 : }
1163 :
1164 :
1165 858561 : void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
1166 : Comment cmnt(masm_, "[ ForStatement");
1167 : // Do not insert break location as we do it below.
1168 79454 : SetStatementPosition(stmt, SKIP_BREAK);
1169 :
1170 : Label test, body;
1171 :
1172 : Iteration loop_statement(this, stmt);
1173 :
1174 79454 : if (stmt->init() != NULL) {
1175 59207 : Visit(stmt->init());
1176 : }
1177 :
1178 : increment_loop_depth();
1179 : // Emit the test at the bottom of the loop (even if empty).
1180 79454 : __ jmp(&test);
1181 :
1182 79454 : PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
1183 79454 : __ bind(&body);
1184 79454 : Visit(stmt->body());
1185 :
1186 79454 : PrepareForBailoutForId(stmt->ContinueId(), BailoutState::NO_REGISTERS);
1187 79454 : __ bind(loop_statement.continue_label());
1188 79454 : if (stmt->next() != NULL) {
1189 64021 : SetStatementPosition(stmt->next());
1190 64021 : Visit(stmt->next());
1191 : }
1192 :
1193 : // Check stack before looping.
1194 79454 : EmitBackEdgeBookkeeping(stmt, &body);
1195 :
1196 79454 : __ bind(&test);
1197 79454 : if (stmt->cond() != NULL) {
1198 73351 : SetExpressionAsStatementPosition(stmt->cond());
1199 : VisitForControl(stmt->cond(),
1200 : &body,
1201 : loop_statement.break_label(),
1202 73351 : loop_statement.break_label());
1203 : } else {
1204 6103 : __ jmp(&body);
1205 : }
1206 :
1207 79454 : PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
1208 79454 : __ bind(loop_statement.break_label());
1209 : decrement_loop_depth();
1210 79454 : }
1211 :
1212 :
1213 0 : void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1214 : // Iterator looping is not supported.
1215 0 : UNREACHABLE();
1216 : }
1217 :
1218 59054 : void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
1219 : LoadFromFrameField(JavaScriptFrameConstants::kFunctionOffset,
1220 29523 : result_register());
1221 29531 : context()->Plug(result_register());
1222 29529 : }
1223 :
1224 0 : void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1225 : // Exception handling is not supported.
1226 0 : UNREACHABLE();
1227 : }
1228 :
1229 :
1230 0 : void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1231 : // Exception handling is not supported.
1232 0 : UNREACHABLE();
1233 : }
1234 :
1235 :
1236 0 : void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1237 : // Debugger statement is not supported.
1238 0 : UNREACHABLE();
1239 : }
1240 :
1241 :
1242 0 : void FullCodeGenerator::VisitCaseClause(CaseClause* clause) {
1243 0 : UNREACHABLE();
1244 : }
1245 :
1246 :
1247 272248 : void FullCodeGenerator::VisitConditional(Conditional* expr) {
1248 : Comment cmnt(masm_, "[ Conditional");
1249 : Label true_case, false_case, done;
1250 22739 : VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
1251 :
1252 22739 : int original_stack_depth = operand_stack_depth_;
1253 22739 : PrepareForBailoutForId(expr->ThenId(), BailoutState::NO_REGISTERS);
1254 22739 : __ bind(&true_case);
1255 : SetExpressionPosition(expr->then_expression());
1256 22739 : if (context()->IsTest()) {
1257 620 : const TestContext* for_test = TestContext::cast(context());
1258 : VisitForControl(expr->then_expression(),
1259 : for_test->true_label(),
1260 : for_test->false_label(),
1261 620 : NULL);
1262 : } else {
1263 22119 : VisitInDuplicateContext(expr->then_expression());
1264 22119 : __ jmp(&done);
1265 : }
1266 :
1267 22739 : operand_stack_depth_ = original_stack_depth;
1268 22739 : PrepareForBailoutForId(expr->ElseId(), BailoutState::NO_REGISTERS);
1269 22739 : __ bind(&false_case);
1270 : SetExpressionPosition(expr->else_expression());
1271 22739 : VisitInDuplicateContext(expr->else_expression());
1272 : // If control flow falls through Visit, merge it with true case here.
1273 22739 : if (!context()->IsTest()) {
1274 22119 : __ bind(&done);
1275 : }
1276 22739 : }
1277 :
1278 :
1279 6415696 : void FullCodeGenerator::VisitLiteral(Literal* expr) {
1280 : Comment cmnt(masm_, "[ Literal");
1281 6415696 : context()->Plug(expr->value());
1282 3207844 : }
1283 :
1284 :
1285 2686840 : void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1286 : Comment cmnt(masm_, "[ FunctionLiteral");
1287 :
1288 : // Build the function boilerplate and instantiate it.
1289 : Handle<SharedFunctionInfo> function_info =
1290 2686835 : Compiler::GetSharedFunctionInfo(expr, script(), info_);
1291 1343423 : if (function_info.is_null()) {
1292 : SetStackOverflow();
1293 1343423 : return;
1294 : }
1295 1343423 : EmitNewClosure(function_info, expr->LiteralFeedbackSlot(), expr->pretenure());
1296 : }
1297 :
1298 :
1299 0 : void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
1300 : // Unsupported
1301 0 : UNREACHABLE();
1302 : }
1303 :
1304 198976 : void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1305 : Comment cmnt(masm_, "[ RegExpLiteral");
1306 24872 : Callable callable = CodeFactory::FastCloneRegExp(isolate());
1307 : CallInterfaceDescriptor descriptor = callable.descriptor();
1308 : LoadFromFrameField(JavaScriptFrameConstants::kFunctionOffset,
1309 24872 : descriptor.GetRegisterParameter(0));
1310 : __ Move(descriptor.GetRegisterParameter(1),
1311 : SmiFromSlot(expr->literal_slot()));
1312 24872 : __ Move(descriptor.GetRegisterParameter(2), expr->pattern());
1313 : __ Move(descriptor.GetRegisterParameter(3), Smi::FromInt(expr->flags()));
1314 24872 : __ Call(callable.code(), RelocInfo::CODE_TARGET);
1315 :
1316 : // Reload the context register after the call as i.e. TurboFan code stubs
1317 : // won't preserve the context register.
1318 : LoadFromFrameField(StandardFrameConstants::kContextOffset,
1319 24872 : context_register());
1320 24872 : context()->Plug(result_register());
1321 24872 : }
1322 :
1323 505 : void FullCodeGenerator::VisitNativeFunctionLiteral(
1324 1010 : NativeFunctionLiteral* expr) {
1325 : Comment cmnt(masm_, "[ NativeFunctionLiteral");
1326 : Handle<SharedFunctionInfo> shared =
1327 505 : Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name());
1328 505 : EmitNewClosure(shared, expr->LiteralFeedbackSlot(), false);
1329 505 : }
1330 :
1331 :
1332 49402 : void FullCodeGenerator::VisitThrow(Throw* expr) {
1333 : Comment cmnt(masm_, "[ Throw");
1334 24701 : VisitForStackValue(expr->exception());
1335 : SetExpressionPosition(expr);
1336 24701 : CallRuntimeWithOperands(Runtime::kThrow);
1337 : // Never returns here.
1338 :
1339 : // Even though this expression doesn't produce a value, we need to simulate
1340 : // plugging of the value context to ensure stack depth tracking is in sync.
1341 24701 : if (context()->IsStackValue()) OperandStackDepthIncrement(1);
1342 24701 : }
1343 :
1344 :
1345 2501100 : void FullCodeGenerator::VisitCall(Call* expr) {
1346 : #ifdef DEBUG
1347 : // We want to verify that RecordJSReturnSite gets called on all paths
1348 : // through this function. Avoid early returns.
1349 : expr->return_is_recorded_ = false;
1350 : #endif
1351 :
1352 : Comment cmnt(masm_, (expr->tail_call_mode() == TailCallMode::kAllow)
1353 : ? "[ TailCall"
1354 : : "[ Call");
1355 : Expression* callee = expr->expression();
1356 1105379 : Call::CallType call_type = expr->GetCallType();
1357 :
1358 : // Eval is unsupported.
1359 1105379 : CHECK(!expr->is_possibly_eval());
1360 :
1361 1105379 : switch (call_type) {
1362 : case Call::GLOBAL_CALL:
1363 317635 : EmitCallWithLoadIC(expr);
1364 317635 : break;
1365 : case Call::NAMED_PROPERTY_CALL: {
1366 991098 : Property* property = callee->AsProperty();
1367 495549 : VisitForStackValue(property->obj());
1368 495549 : EmitCallWithLoadIC(expr);
1369 495549 : break;
1370 : }
1371 : case Call::KEYED_PROPERTY_CALL: {
1372 5571 : Property* property = callee->AsProperty();
1373 1857 : VisitForStackValue(property->obj());
1374 1857 : EmitKeyedCallWithLoadIC(expr, property->key());
1375 1857 : break;
1376 : }
1377 : case Call::OTHER_CALL:
1378 : // Call to an arbitrary expression not handled specially above.
1379 290334 : VisitForStackValue(callee);
1380 : OperandStackDepthIncrement(1);
1381 290342 : __ PushRoot(Heap::kUndefinedValueRootIndex);
1382 : // Emit function call.
1383 290342 : EmitCall(expr);
1384 290340 : break;
1385 : case Call::NAMED_SUPER_PROPERTY_CALL:
1386 : case Call::KEYED_SUPER_PROPERTY_CALL:
1387 : case Call::SUPER_CALL:
1388 : case Call::WITH_CALL:
1389 0 : UNREACHABLE();
1390 : }
1391 :
1392 : #ifdef DEBUG
1393 : // RecordJSReturnSite should have been called.
1394 : DCHECK(expr->return_is_recorded_);
1395 : #endif
1396 1105385 : }
1397 :
1398 1046188 : void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
1399 : ZoneList<Expression*>* args = expr->arguments();
1400 303978 : int arg_count = args->length();
1401 :
1402 303978 : if (expr->is_jsruntime()) {
1403 : Comment cmnt(masm_, "[ CallRuntime");
1404 20986 : EmitLoadJSRuntimeFunction(expr);
1405 :
1406 : // Push the arguments ("left-to-right").
1407 66349 : for (int i = 0; i < arg_count; i++) {
1408 45363 : VisitForStackValue(args->at(i));
1409 : }
1410 :
1411 20986 : PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
1412 20986 : EmitCallJSRuntimeFunction(expr);
1413 20986 : context()->DropAndPlug(1, result_register());
1414 :
1415 : } else {
1416 : const Runtime::Function* function = expr->function();
1417 282992 : switch (function->function_id) {
1418 : #define CALL_INTRINSIC_GENERATOR(Name) \
1419 : case Runtime::kInline##Name: { \
1420 : Comment cmnt(masm_, "[ Inline" #Name); \
1421 : return Emit##Name(expr); \
1422 : }
1423 3162 : FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
1424 : #undef CALL_INTRINSIC_GENERATOR
1425 : default: {
1426 : Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
1427 : // Push the arguments ("left-to-right").
1428 403477 : for (int i = 0; i < arg_count; i++) {
1429 403477 : VisitForStackValue(args->at(i));
1430 : }
1431 :
1432 : // Call the C runtime function.
1433 208623 : PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
1434 208623 : __ CallRuntime(expr->function(), arg_count);
1435 : OperandStackDepthDecrement(arg_count);
1436 208623 : context()->Plug(result_register());
1437 : }
1438 : }
1439 : }
1440 : }
1441 :
1442 0 : void FullCodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
1443 :
1444 :
1445 0 : void FullCodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
1446 0 : UNREACHABLE();
1447 : }
1448 :
1449 0 : void FullCodeGenerator::VisitGetIterator(GetIterator* expr) { UNREACHABLE(); }
1450 :
1451 0 : void FullCodeGenerator::VisitImportCallExpression(ImportCallExpression* expr) {
1452 0 : UNREACHABLE();
1453 : }
1454 :
1455 54 : void FullCodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
1456 54 : Visit(expr->expression());
1457 54 : }
1458 :
1459 :
1460 569677 : bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
1461 : Expression* sub_expr;
1462 : Literal* literal;
1463 569677 : if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
1464 : SetExpressionPosition(expr);
1465 : EmitLiteralCompareTypeof(expr, sub_expr,
1466 117146 : Handle<String>::cast(literal->value()));
1467 58573 : return true;
1468 : }
1469 :
1470 511103 : if (expr->IsLiteralCompareUndefined(&sub_expr)) {
1471 : SetExpressionPosition(expr);
1472 40694 : EmitLiteralCompareNil(expr, sub_expr, kUndefinedValue);
1473 40694 : return true;
1474 : }
1475 :
1476 470409 : if (expr->IsLiteralCompareNull(&sub_expr)) {
1477 : SetExpressionPosition(expr);
1478 21918 : EmitLiteralCompareNil(expr, sub_expr, kNullValue);
1479 21918 : return true;
1480 : }
1481 :
1482 : return false;
1483 : }
1484 :
1485 :
1486 10638 : void BackEdgeTable::Patch(Isolate* isolate, Code* unoptimized) {
1487 : DisallowHeapAllocation no_gc;
1488 : Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement);
1489 :
1490 : // Increment loop nesting level by one and iterate over the back edge table
1491 : // to find the matching loops to patch the interrupt
1492 : // call to an unconditional call to the replacement code.
1493 10638 : int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level() + 1;
1494 21276 : if (loop_nesting_level > AbstractCode::kMaxLoopNestingMarker) return;
1495 :
1496 : BackEdgeTable back_edges(unoptimized, &no_gc);
1497 28625 : for (uint32_t i = 0; i < back_edges.length(); i++) {
1498 19182 : if (static_cast<int>(back_edges.loop_depth(i)) == loop_nesting_level) {
1499 : DCHECK_EQ(INTERRUPT, GetBackEdgeState(isolate,
1500 : unoptimized,
1501 : back_edges.pc(i)));
1502 4831 : PatchAt(unoptimized, back_edges.pc(i), ON_STACK_REPLACEMENT, patch);
1503 : }
1504 : }
1505 :
1506 : unoptimized->set_allow_osr_at_loop_nesting_level(loop_nesting_level);
1507 : DCHECK(Verify(isolate, unoptimized));
1508 : }
1509 :
1510 :
1511 2641 : void BackEdgeTable::Revert(Isolate* isolate, Code* unoptimized) {
1512 : DisallowHeapAllocation no_gc;
1513 : Code* patch = isolate->builtins()->builtin(Builtins::kInterruptCheck);
1514 :
1515 : // Iterate over the back edge table and revert the patched interrupt calls.
1516 : int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
1517 :
1518 : BackEdgeTable back_edges(unoptimized, &no_gc);
1519 7774 : for (uint32_t i = 0; i < back_edges.length(); i++) {
1520 5133 : if (static_cast<int>(back_edges.loop_depth(i)) <= loop_nesting_level) {
1521 : DCHECK_NE(INTERRUPT, GetBackEdgeState(isolate,
1522 : unoptimized,
1523 : back_edges.pc(i)));
1524 4824 : PatchAt(unoptimized, back_edges.pc(i), INTERRUPT, patch);
1525 : }
1526 : }
1527 :
1528 : unoptimized->set_allow_osr_at_loop_nesting_level(0);
1529 : // Assert that none of the back edges are patched anymore.
1530 : DCHECK(Verify(isolate, unoptimized));
1531 2641 : }
1532 :
1533 :
1534 : #ifdef DEBUG
1535 : bool BackEdgeTable::Verify(Isolate* isolate, Code* unoptimized) {
1536 : DisallowHeapAllocation no_gc;
1537 : int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
1538 : BackEdgeTable back_edges(unoptimized, &no_gc);
1539 : for (uint32_t i = 0; i < back_edges.length(); i++) {
1540 : uint32_t loop_depth = back_edges.loop_depth(i);
1541 : CHECK_LE(static_cast<int>(loop_depth), AbstractCode::kMaxLoopNestingMarker);
1542 : // Assert that all back edges for shallower loops (and only those)
1543 : // have already been patched.
1544 : CHECK_EQ((static_cast<int>(loop_depth) <= loop_nesting_level),
1545 : GetBackEdgeState(isolate,
1546 : unoptimized,
1547 : back_edges.pc(i)) != INTERRUPT);
1548 : }
1549 : return true;
1550 : }
1551 : #endif // DEBUG
1552 :
1553 :
1554 1985675 : FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded(
1555 45958 : FullCodeGenerator* codegen, Scope* scope, BailoutId entry_id,
1556 : BailoutId declarations_id, BailoutId exit_id)
1557 1985675 : : codegen_(codegen), exit_id_(exit_id) {
1558 1985675 : saved_scope_ = codegen_->scope();
1559 :
1560 1985675 : if (scope == NULL) {
1561 1939717 : codegen_->PrepareForBailoutForId(entry_id, BailoutState::NO_REGISTERS);
1562 1939717 : needs_block_context_ = false;
1563 : } else {
1564 45958 : needs_block_context_ = scope->NeedsContext();
1565 45958 : codegen_->scope_ = scope;
1566 : {
1567 45958 : if (needs_block_context_) {
1568 : Comment cmnt(masm(), "[ Extend block context");
1569 : codegen_->PushOperand(scope->scope_info());
1570 4608 : codegen_->PushFunctionArgumentForContextAllocation();
1571 4608 : codegen_->CallRuntimeWithOperands(Runtime::kPushBlockContext);
1572 :
1573 : // Replace the context stored in the frame.
1574 : codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
1575 4608 : codegen_->context_register());
1576 : }
1577 45958 : CHECK_EQ(0, scope->num_stack_slots());
1578 45958 : codegen_->PrepareForBailoutForId(entry_id, BailoutState::NO_REGISTERS);
1579 : }
1580 : {
1581 : Comment cmnt(masm(), "[ Declarations");
1582 45958 : codegen_->VisitDeclarations(scope->declarations());
1583 : codegen_->PrepareForBailoutForId(declarations_id,
1584 45958 : BailoutState::NO_REGISTERS);
1585 : }
1586 : }
1587 1985675 : }
1588 :
1589 :
1590 1985674 : FullCodeGenerator::EnterBlockScopeIfNeeded::~EnterBlockScopeIfNeeded() {
1591 1985674 : if (needs_block_context_) {
1592 : codegen_->LoadContextField(codegen_->context_register(),
1593 4608 : Context::PREVIOUS_INDEX);
1594 : // Update local stack frame context field.
1595 : codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
1596 4608 : codegen_->context_register());
1597 : }
1598 1985674 : codegen_->PrepareForBailoutForId(exit_id_, BailoutState::NO_REGISTERS);
1599 1985674 : codegen_->scope_ = saved_scope_;
1600 1985674 : }
1601 :
1602 1429748 : Handle<Script> FullCodeGenerator::script() { return info_->script(); }
1603 :
1604 1201322 : LanguageMode FullCodeGenerator::language_mode() {
1605 27945 : return scope()->language_mode();
1606 : }
1607 :
1608 1402 : bool FullCodeGenerator::has_simple_parameters() {
1609 1402 : return info_->has_simple_parameters();
1610 : }
1611 :
1612 3243216 : FunctionLiteral* FullCodeGenerator::literal() const { return info_->literal(); }
1613 :
1614 0 : const FeedbackVectorSpec* FullCodeGenerator::feedback_vector_spec() const {
1615 0 : return literal()->feedback_vector_spec();
1616 : }
1617 :
1618 : #undef __
1619 :
1620 :
1621 : } // namespace internal
1622 : } // namespace v8
|