blob: cb8f4aafcd9cd7274f032f14505f5dd028725252 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Leon Clarked91b9f72010-01-27 17:25:45 +00004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/v8.h"
Leon Clarked91b9f72010-01-27 17:25:45 +00006
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007#include "src/ast.h"
8#include "src/ast-numbering.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/code-factory.h"
10#include "src/codegen.h"
11#include "src/compiler.h"
12#include "src/debug.h"
13#include "src/full-codegen.h"
14#include "src/liveedit.h"
15#include "src/macro-assembler.h"
16#include "src/prettyprinter.h"
17#include "src/scopeinfo.h"
18#include "src/scopes.h"
19#include "src/snapshot.h"
Leon Clarked91b9f72010-01-27 17:25:45 +000020
21namespace v8 {
22namespace internal {
23
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010024void BreakableStatementChecker::Check(Statement* stmt) {
25 Visit(stmt);
26}
27
28
29void BreakableStatementChecker::Check(Expression* expr) {
30 Visit(expr);
31}
32
33
Ben Murdoch3ef787d2012-04-12 10:51:47 +010034void BreakableStatementChecker::VisitVariableDeclaration(
35 VariableDeclaration* decl) {
36}
37
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038
Ben Murdoch3ef787d2012-04-12 10:51:47 +010039void BreakableStatementChecker::VisitFunctionDeclaration(
40 FunctionDeclaration* decl) {
41}
42
Ben Murdochb8a8cc12014-11-26 15:28:44 +000043
Ben Murdoch3ef787d2012-04-12 10:51:47 +010044void BreakableStatementChecker::VisitModuleDeclaration(
45 ModuleDeclaration* decl) {
46}
47
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048
Ben Murdoch3ef787d2012-04-12 10:51:47 +010049void BreakableStatementChecker::VisitImportDeclaration(
50 ImportDeclaration* decl) {
51}
52
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053
Ben Murdoch3ef787d2012-04-12 10:51:47 +010054void BreakableStatementChecker::VisitExportDeclaration(
55 ExportDeclaration* decl) {
56}
57
58
59void BreakableStatementChecker::VisitModuleLiteral(ModuleLiteral* module) {
60}
61
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062
Ben Murdoch3ef787d2012-04-12 10:51:47 +010063void BreakableStatementChecker::VisitModuleVariable(ModuleVariable* module) {
64}
65
Ben Murdochb8a8cc12014-11-26 15:28:44 +000066
Ben Murdoch3ef787d2012-04-12 10:51:47 +010067void BreakableStatementChecker::VisitModulePath(ModulePath* module) {
68}
69
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070
Ben Murdoch3ef787d2012-04-12 10:51:47 +010071void BreakableStatementChecker::VisitModuleUrl(ModuleUrl* module) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010072}
73
74
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075void BreakableStatementChecker::VisitModuleStatement(ModuleStatement* stmt) {
76}
77
78
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +010079void BreakableStatementChecker::VisitBlock(Block* stmt) {
80}
81
82
83void BreakableStatementChecker::VisitExpressionStatement(
84 ExpressionStatement* stmt) {
85 // Check if expression is breakable.
86 Visit(stmt->expression());
87}
88
89
90void BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) {
91}
92
93
94void BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) {
95 // If the condition is breakable the if statement is breakable.
96 Visit(stmt->condition());
97}
98
99
100void BreakableStatementChecker::VisitContinueStatement(
101 ContinueStatement* stmt) {
102}
103
104
105void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
106}
107
108
109void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
110 // Return is breakable if the expression is.
111 Visit(stmt->expression());
112}
113
114
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000115void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100116 Visit(stmt->expression());
117}
118
119
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100120void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
121 // Switch statements breakable if the tag expression is.
122 Visit(stmt->tag());
123}
124
125
126void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
127 // Mark do while as breakable to avoid adding a break slot in front of it.
128 is_breakable_ = true;
129}
130
131
132void BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) {
133 // Mark while statements breakable if the condition expression is.
134 Visit(stmt->cond());
135}
136
137
138void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400139 // We set positions for both init and condition, if they exist.
140 if (stmt->cond() != NULL || stmt->init() != NULL) is_breakable_ = true;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100141}
142
143
144void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400145 // For-in is breakable because we set the position for the enumerable.
146 is_breakable_ = true;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100147}
148
149
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150void BreakableStatementChecker::VisitForOfStatement(ForOfStatement* stmt) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400151 // For-of is breakable because we set the position for the next() call.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152 is_breakable_ = true;
153}
154
155
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100156void BreakableStatementChecker::VisitTryCatchStatement(
157 TryCatchStatement* stmt) {
158 // Mark try catch as breakable to avoid adding a break slot in front of it.
159 is_breakable_ = true;
160}
161
162
163void BreakableStatementChecker::VisitTryFinallyStatement(
164 TryFinallyStatement* stmt) {
165 // Mark try finally as breakable to avoid adding a break slot in front of it.
166 is_breakable_ = true;
167}
168
169
170void BreakableStatementChecker::VisitDebuggerStatement(
171 DebuggerStatement* stmt) {
172 // The debugger statement is breakable.
173 is_breakable_ = true;
174}
175
176
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177void BreakableStatementChecker::VisitCaseClause(CaseClause* clause) {
178}
179
180
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100181void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
182}
183
184
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185void BreakableStatementChecker::VisitClassLiteral(ClassLiteral* expr) {
186 if (expr->extends() != NULL) {
187 Visit(expr->extends());
188 }
189}
190
191
192void BreakableStatementChecker::VisitNativeFunctionLiteral(
193 NativeFunctionLiteral* expr) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100194}
195
196
197void BreakableStatementChecker::VisitConditional(Conditional* expr) {
198}
199
200
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100201void BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) {
202}
203
204
205void BreakableStatementChecker::VisitLiteral(Literal* expr) {
206}
207
208
209void BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
210}
211
212
213void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) {
214}
215
216
217void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
218}
219
220
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100221void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
222 // If assigning to a property (including a global property) the assignment is
223 // breakable.
Ben Murdoch589d6972011-11-30 16:04:58 +0000224 VariableProxy* proxy = expr->target()->AsVariableProxy();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100225 Property* prop = expr->target()->AsProperty();
Ben Murdoch589d6972011-11-30 16:04:58 +0000226 if (prop != NULL || (proxy != NULL && proxy->var()->IsUnallocated())) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100227 is_breakable_ = true;
228 return;
229 }
230
231 // Otherwise the assignment is breakable if the assigned value is.
232 Visit(expr->value());
233}
234
235
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236void BreakableStatementChecker::VisitYield(Yield* expr) {
237 // Yield is breakable if the expression is.
238 Visit(expr->expression());
239}
240
241
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100242void BreakableStatementChecker::VisitThrow(Throw* expr) {
243 // Throw is breakable if the expression is.
244 Visit(expr->exception());
245}
246
247
248void BreakableStatementChecker::VisitProperty(Property* expr) {
249 // Property load is breakable.
250 is_breakable_ = true;
251}
252
253
254void BreakableStatementChecker::VisitCall(Call* expr) {
255 // Function calls both through IC and call stub are breakable.
256 is_breakable_ = true;
257}
258
259
260void BreakableStatementChecker::VisitCallNew(CallNew* expr) {
261 // Function calls through new are breakable.
262 is_breakable_ = true;
263}
264
265
266void BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) {
267}
268
269
270void BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) {
271 Visit(expr->expression());
272}
273
274
275void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
276 Visit(expr->expression());
277}
278
279
280void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
281 Visit(expr->left());
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +0100282 if (expr->op() != Token::AND &&
283 expr->op() != Token::OR) {
284 Visit(expr->right());
285 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100286}
287
288
289void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
290 Visit(expr->left());
291 Visit(expr->right());
292}
293
294
295void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
296}
297
298
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000299void BreakableStatementChecker::VisitSuperReference(SuperReference* expr) {}
300
301
Leon Clarked91b9f72010-01-27 17:25:45 +0000302#define __ ACCESS_MASM(masm())
303
Ben Murdochf87a2032010-10-22 12:50:53 +0100304bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
Steve Block44f0eee2011-05-26 01:26:41 +0100305 Isolate* isolate = info->isolate();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306
307 TimerEventScope<TimerEventCompileFullCode> timer(info->isolate());
308
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400309 // Ensure that the feedback vector is large enough.
310 info->EnsureFeedbackVector();
311
Andrei Popescu31002712010-02-23 13:46:05 +0000312 Handle<Script> script = info->script();
Leon Clarked91b9f72010-01-27 17:25:45 +0000313 if (!script->IsUndefined() && !script->source()->IsUndefined()) {
314 int len = String::cast(script->source())->length();
Steve Block44f0eee2011-05-26 01:26:41 +0100315 isolate->counters()->total_full_codegen_source_size()->Increment(len);
Leon Clarked91b9f72010-01-27 17:25:45 +0000316 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317 CodeGenerator::MakeCodePrologue(info, "full");
Leon Clarked91b9f72010-01-27 17:25:45 +0000318 const int kInitialBufferSize = 4 * KB;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100319 MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 if (info->will_serialize()) masm.enable_serializer();
321
322 LOG_CODE_EVENT(isolate,
323 CodeStartLinePosInfoRecordEvent(masm.positions_recorder()));
Andrei Popescu402d9372010-02-26 13:31:12 +0000324
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100325 FullCodeGenerator cgen(&masm, info);
326 cgen.Generate();
Leon Clarked91b9f72010-01-27 17:25:45 +0000327 if (cgen.HasStackOverflow()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328 DCHECK(!isolate->has_pending_exception());
Ben Murdochf87a2032010-10-22 12:50:53 +0100329 return false;
Leon Clarked91b9f72010-01-27 17:25:45 +0000330 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000331 unsigned table_offset = cgen.EmitBackEdgeTable();
Ben Murdochf87a2032010-10-22 12:50:53 +0100332
Ben Murdoch589d6972011-11-30 16:04:58 +0000333 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
Ben Murdochf87a2032010-10-22 12:50:53 +0100334 Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100335 code->set_optimizable(info->IsOptimizable() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000336 !info->function()->dont_optimize() &&
337 info->function()->scope()->AllowsLazyCompilation());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100338 cgen.PopulateDeoptimizationData(code);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100339 cgen.PopulateTypeFeedbackInfo(code);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100340 code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400341 code->set_has_reloc_info_for_serialization(info->will_serialize());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100342 code->set_handler_table(*cgen.handler_table());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100343 code->set_compiled_optimizable(info->IsOptimizable());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100344 code->set_allow_osr_at_loop_nesting_level(0);
Ben Murdoch8f9999f2012-04-23 10:39:17 +0100345 code->set_profiler_ticks(0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346 code->set_back_edge_table_offset(table_offset);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100347 CodeGenerator::PrintCode(code, info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 info->SetCode(code);
349 void* line_info = masm.positions_recorder()->DetachJITHandlerData();
350 LOG_CODE_EVENT(isolate, CodeEndLinePosInfoRecordEvent(*code, line_info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400351
352#ifdef DEBUG
353 // Check that no context-specific object has been embedded.
354 code->VerifyEmbeddedObjectsInFullCode();
355#endif // DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356 return true;
Leon Clarked91b9f72010-01-27 17:25:45 +0000357}
358
359
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360unsigned FullCodeGenerator::EmitBackEdgeTable() {
361 // The back edge table consists of a length (in number of entries)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100362 // field, and then a sequence of entries. Each entry is a pair of AST id
363 // and code-relative pc offset.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364 masm()->Align(kPointerSize);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100365 unsigned offset = masm()->pc_offset();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000366 unsigned length = back_edges_.length();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100367 __ dd(length);
368 for (unsigned i = 0; i < length; ++i) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 __ dd(back_edges_[i].id.ToInt());
370 __ dd(back_edges_[i].pc);
371 __ dd(back_edges_[i].loop_depth);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100372 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100373 return offset;
374}
375
376
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400377void FullCodeGenerator::EnsureSlotContainsAllocationSite(
378 FeedbackVectorSlot slot) {
379 Handle<TypeFeedbackVector> vector = FeedbackVector();
380 if (!vector->Get(slot)->IsAllocationSite()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000381 Handle<AllocationSite> allocation_site =
382 isolate()->factory()->NewAllocationSite();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400383 vector->Set(slot, *allocation_site);
384 }
385}
386
387
388void FullCodeGenerator::EnsureSlotContainsAllocationSite(
389 FeedbackVectorICSlot slot) {
390 Handle<TypeFeedbackVector> vector = FeedbackVector();
391 if (!vector->Get(slot)->IsAllocationSite()) {
392 Handle<AllocationSite> allocation_site =
393 isolate()->factory()->NewAllocationSite();
394 vector->Set(slot, *allocation_site);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 }
396}
397
398
Ben Murdochb0fe1622011-05-05 13:52:32 +0100399void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
400 // Fill in the deoptimization information.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000401 DCHECK(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100402 if (!info_->HasDeoptimizationSupport()) return;
403 int length = bailout_entries_.length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000404 Handle<DeoptimizationOutputData> data =
405 DeoptimizationOutputData::New(isolate(), length, TENURED);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100406 for (int i = 0; i < length; i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407 data->SetAstId(i, bailout_entries_[i].id);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100408 data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
409 }
410 code->set_deoptimization_data(*data);
411}
412
413
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100414void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
415 Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo();
416 info->set_ic_total_count(ic_total_count_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000417 DCHECK(!isolate()->heap()->InNewSpace(*info));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100418 code->set_type_feedback_info(*info);
419}
420
421
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422void FullCodeGenerator::Initialize() {
423 InitializeAstVisitor(info_->zone());
424 // The generation of debug code must match between the snapshot code and the
425 // code that is generated later. This is assumed by the debugger when it is
426 // calculating PC offsets after generating a debug version of code. Therefore
427 // we disable the production of debug code in the full compiler if we are
428 // either generating a snapshot or we booted from a snapshot.
429 generate_debug_code_ = FLAG_debug_code &&
430 !masm_->serializer_enabled() &&
431 !Snapshot::HaveASnapshotToStartFrom();
432 masm_->set_emit_debug_code(generate_debug_code_);
433 masm_->set_predictable_code_size(true);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100434}
435
436
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000437void FullCodeGenerator::PrepareForBailout(Expression* node, State state) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100438 PrepareForBailoutForId(node->id(), state);
439}
440
441
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000442void FullCodeGenerator::CallLoadIC(ContextualMode contextual_mode,
443 TypeFeedbackId id) {
444 Handle<Code> ic = CodeFactory::LoadIC(isolate(), contextual_mode).code();
445 CallIC(ic, id);
446}
447
448
449void FullCodeGenerator::CallStoreIC(TypeFeedbackId id) {
450 Handle<Code> ic = CodeFactory::StoreIC(isolate(), strict_mode()).code();
451 CallIC(ic, id);
452}
453
454
Ben Murdochb0fe1622011-05-05 13:52:32 +0100455void FullCodeGenerator::RecordJSReturnSite(Call* call) {
456 // We record the offset of the function return so we can rebuild the frame
457 // if the function was inlined, i.e., this is the return address in the
458 // inlined function's frame.
459 //
460 // The state is ignored. We defensively set it to TOS_REG, which is the
461 // real state of the unoptimized code at the return site.
462 PrepareForBailoutForId(call->ReturnId(), TOS_REG);
463#ifdef DEBUG
464 // In debug builds, mark the return so we can verify that this function
465 // was called.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000466 DCHECK(!call->return_is_recorded_);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100467 call->return_is_recorded_ = true;
468#endif
469}
470
471
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000472void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100473 // There's no need to prepare this code for bailouts from already optimized
474 // code or code that can't be optimized.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100475 if (!info_->HasDeoptimizationSupport()) return;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100476 unsigned pc_and_state =
477 StateField::encode(state) | PcField::encode(masm_->pc_offset());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000478 DCHECK(Smi::IsValid(pc_and_state));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100479#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000480 for (int i = 0; i < bailout_entries_.length(); ++i) {
481 DCHECK(bailout_entries_[i].id != id);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100482 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000483#endif
484 BailoutEntry entry = { id, pc_and_state };
485 bailout_entries_.Add(entry, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100486}
487
488
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000489void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) {
490 // The pc offset does not need to be encoded and packed together with a state.
491 DCHECK(masm_->pc_offset() > 0);
492 DCHECK(loop_depth() > 0);
493 uint8_t depth = Min(loop_depth(), Code::kMaxLoopNestingMarker);
494 BackEdgeEntry entry =
495 { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth };
496 back_edges_.Add(entry, zone());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100497}
498
499
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100500bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100501 // Inline smi case inside loops, but not division and modulo which
502 // are too complicated and take up too much space.
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100503 if (op == Token::DIV ||op == Token::MOD) return false;
504 if (FLAG_always_inline_smi_code) return true;
505 return loop_depth_ > 0;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100506}
507
508
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100509void FullCodeGenerator::EffectContext::Plug(Register reg) const {
510}
511
512
513void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100514 __ Move(result_register(), reg);
515}
516
517
518void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000519 __ Push(reg);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100520}
521
522
523void FullCodeGenerator::TestContext::Plug(Register reg) const {
524 // For simplicity we always test the accumulator register.
525 __ Move(result_register(), reg);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100526 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000527 codegen()->DoTest(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100528}
529
530
531void FullCodeGenerator::EffectContext::PlugTOS() const {
532 __ Drop(1);
533}
534
535
536void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000537 __ Pop(result_register());
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100538}
539
540
541void FullCodeGenerator::StackValueContext::PlugTOS() const {
542}
543
544
545void FullCodeGenerator::TestContext::PlugTOS() const {
546 // For simplicity we always test the accumulator register.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547 __ Pop(result_register());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100548 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000549 codegen()->DoTest(this);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100550}
551
552
553void FullCodeGenerator::EffectContext::PrepareTest(
554 Label* materialize_true,
555 Label* materialize_false,
556 Label** if_true,
557 Label** if_false,
558 Label** fall_through) const {
559 // In an effect context, the true and the false case branch to the
560 // same label.
561 *if_true = *if_false = *fall_through = materialize_true;
562}
563
564
565void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
566 Label* materialize_true,
567 Label* materialize_false,
568 Label** if_true,
569 Label** if_false,
570 Label** fall_through) const {
571 *if_true = *fall_through = materialize_true;
572 *if_false = materialize_false;
573}
574
575
576void FullCodeGenerator::StackValueContext::PrepareTest(
577 Label* materialize_true,
578 Label* materialize_false,
579 Label** if_true,
580 Label** if_false,
581 Label** fall_through) const {
582 *if_true = *fall_through = materialize_true;
583 *if_false = materialize_false;
584}
585
586
587void FullCodeGenerator::TestContext::PrepareTest(
588 Label* materialize_true,
589 Label* materialize_false,
590 Label** if_true,
591 Label** if_false,
592 Label** fall_through) const {
593 *if_true = true_label_;
594 *if_false = false_label_;
595 *fall_through = fall_through_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100596}
597
598
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000599void FullCodeGenerator::DoTest(const TestContext* context) {
600 DoTest(context->condition(),
601 context->true_label(),
602 context->false_label(),
603 context->fall_through());
604}
605
606
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000607void FullCodeGenerator::AllocateModules(ZoneList<Declaration*>* declarations) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608 DCHECK(scope_->is_script_scope());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609
610 for (int i = 0; i < declarations->length(); i++) {
611 ModuleDeclaration* declaration = declarations->at(i)->AsModuleDeclaration();
612 if (declaration != NULL) {
613 ModuleLiteral* module = declaration->module()->AsModuleLiteral();
614 if (module != NULL) {
615 Comment cmnt(masm_, "[ Link nested modules");
616 Scope* scope = module->body()->scope();
617 Interface* interface = scope->interface();
618 DCHECK(interface->IsModule() && interface->IsFrozen());
619
620 interface->Allocate(scope->module_var()->index());
621
622 // Set up module context.
623 DCHECK(scope->interface()->Index() >= 0);
624 __ Push(Smi::FromInt(scope->interface()->Index()));
625 __ Push(scope->GetScopeInfo());
626 __ CallRuntime(Runtime::kPushModuleContext, 2);
627 StoreToFrameField(StandardFrameConstants::kContextOffset,
628 context_register());
629
630 AllocateModules(scope->declarations());
631
632 // Pop module context.
633 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
634 // Update local stack frame context field.
635 StoreToFrameField(StandardFrameConstants::kContextOffset,
636 context_register());
637 }
638 }
639 }
640}
641
642
643// Modules have their own local scope, represented by their own context.
644// Module instance objects have an accessor for every export that forwards
645// access to the respective slot from the module's context. (Exports that are
646// modules themselves, however, are simple data properties.)
647//
648// All modules have a _hosting_ scope/context, which (currently) is the
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400649// enclosing script scope. To deal with recursion, nested modules are hosted
650// by the same scope as global ones.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000651//
652// For every (global or nested) module literal, the hosting context has an
653// internal slot that points directly to the respective module context. This
654// enables quick access to (statically resolved) module members by 2-dimensional
655// access through the hosting context. For example,
656//
657// module A {
658// let x;
659// module B { let y; }
660// }
661// module C { let z; }
662//
663// allocates contexts as follows:
664//
665// [header| .A | .B | .C | A | C ] (global)
666// | | |
667// | | +-- [header| z ] (module)
668// | |
669// | +------- [header| y ] (module)
670// |
671// +------------ [header| x | B ] (module)
672//
673// Here, .A, .B, .C are the internal slots pointing to the hosted module
674// contexts, whereas A, B, C hold the actual instance objects (note that every
675// module context also points to the respective instance object through its
676// extension slot in the header).
677//
678// To deal with arbitrary recursion and aliases between modules,
679// they are created and initialized in several stages. Each stage applies to
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400680// all modules in the hosting script scope, including nested ones.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000681//
682// 1. Allocate: for each module _literal_, allocate the module contexts and
683// respective instance object and wire them up. This happens in the
684// PushModuleContext runtime function, as generated by AllocateModules
685// (invoked by VisitDeclarations in the hosting scope).
686//
687// 2. Bind: for each module _declaration_ (i.e. literals as well as aliases),
688// assign the respective instance object to respective local variables. This
689// happens in VisitModuleDeclaration, and uses the instance objects created
690// in the previous stage.
691// For each module _literal_, this phase also constructs a module descriptor
692// for the next stage. This happens in VisitModuleLiteral.
693//
694// 3. Populate: invoke the DeclareModules runtime function to populate each
695// _instance_ object with accessors for it exports. This is generated by
696// DeclareModules (invoked by VisitDeclarations in the hosting scope again),
697// and uses the descriptors generated in the previous stage.
698//
699// 4. Initialize: execute the module bodies (and other code) in sequence. This
700// happens by the separate statements generated for module bodies. To reenter
701// the module scopes properly, the parser inserted ModuleStatements.
702
Leon Clarked91b9f72010-01-27 17:25:45 +0000703void FullCodeGenerator::VisitDeclarations(
704 ZoneList<Declaration*>* declarations) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000705 Handle<FixedArray> saved_modules = modules_;
706 int saved_module_index = module_index_;
707 ZoneList<Handle<Object> >* saved_globals = globals_;
708 ZoneList<Handle<Object> > inner_globals(10, zone());
709 globals_ = &inner_globals;
710
711 if (scope_->num_modules() != 0) {
712 // This is a scope hosting modules. Allocate a descriptor array to pass
713 // to the runtime for initialization.
714 Comment cmnt(masm_, "[ Allocate modules");
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400715 DCHECK(scope_->is_script_scope());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000716 modules_ =
717 isolate()->factory()->NewFixedArray(scope_->num_modules(), TENURED);
718 module_index_ = 0;
719
720 // Generate code for allocating all modules, including nested ones.
721 // The allocated contexts are stored in internal variables in this scope.
722 AllocateModules(declarations);
723 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100724
725 AstVisitor::VisitDeclarations(declarations);
Leon Clarked91b9f72010-01-27 17:25:45 +0000726
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000727 if (scope_->num_modules() != 0) {
728 // Initialize modules from descriptor array.
729 DCHECK(module_index_ == modules_->length());
730 DeclareModules(modules_);
731 modules_ = saved_modules;
732 module_index_ = saved_module_index;
733 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000734
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000735 if (!globals_->is_empty()) {
Leon Clarked91b9f72010-01-27 17:25:45 +0000736 // Invoke the platform-dependent code generator to do the actual
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737 // declaration of the global functions and variables.
738 Handle<FixedArray> array =
739 isolate()->factory()->NewFixedArray(globals_->length(), TENURED);
740 for (int i = 0; i < globals_->length(); ++i)
741 array->set(i, *globals_->at(i));
Leon Clarked91b9f72010-01-27 17:25:45 +0000742 DeclareGlobals(array);
743 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100744
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000745 globals_ = saved_globals;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100746}
747
748
749void FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000750 Block* block = module->body();
751 Scope* saved_scope = scope();
752 scope_ = block->scope();
753 Interface* interface = scope_->interface();
754
755 Comment cmnt(masm_, "[ ModuleLiteral");
756 SetStatementPosition(block);
757
758 DCHECK(!modules_.is_null());
759 DCHECK(module_index_ < modules_->length());
760 int index = module_index_++;
761
762 // Set up module context.
763 DCHECK(interface->Index() >= 0);
764 __ Push(Smi::FromInt(interface->Index()));
765 __ Push(Smi::FromInt(0));
766 __ CallRuntime(Runtime::kPushModuleContext, 2);
767 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
768
769 {
770 Comment cmnt(masm_, "[ Declarations");
771 VisitDeclarations(scope_->declarations());
772 }
773
774 // Populate the module description.
775 Handle<ModuleInfo> description =
776 ModuleInfo::Create(isolate(), interface, scope_);
777 modules_->set(index, *description);
778
779 scope_ = saved_scope;
780 // Pop module context.
781 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
782 // Update local stack frame context field.
783 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100784}
785
786
787void FullCodeGenerator::VisitModuleVariable(ModuleVariable* module) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000788 // Nothing to do.
789 // The instance object is resolved statically through the module's interface.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100790}
791
792
793void FullCodeGenerator::VisitModulePath(ModulePath* module) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794 // Nothing to do.
795 // The instance object is resolved statically through the module's interface.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100796}
797
798
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000799void FullCodeGenerator::VisitModuleUrl(ModuleUrl* module) {
800 // TODO(rossberg): dummy allocation for now.
801 Scope* scope = module->body()->scope();
802 Interface* interface = scope_->interface();
803
804 DCHECK(interface->IsModule() && interface->IsFrozen());
805 DCHECK(!modules_.is_null());
806 DCHECK(module_index_ < modules_->length());
807 interface->Allocate(scope->module_var()->index());
808 int index = module_index_++;
809
810 Handle<ModuleInfo> description =
811 ModuleInfo::Create(isolate(), interface, scope_);
812 modules_->set(index, *description);
Leon Clarked91b9f72010-01-27 17:25:45 +0000813}
814
815
Ben Murdoch589d6972011-11-30 16:04:58 +0000816int FullCodeGenerator::DeclareGlobalsFlags() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817 DCHECK(DeclareGlobalsStrictMode::is_valid(strict_mode()));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100818 return DeclareGlobalsEvalFlag::encode(is_eval()) |
819 DeclareGlobalsNativeFlag::encode(is_native()) |
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000820 DeclareGlobalsStrictMode::encode(strict_mode());
Ben Murdoch589d6972011-11-30 16:04:58 +0000821}
822
823
Leon Clarked91b9f72010-01-27 17:25:45 +0000824void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000825 CodeGenerator::RecordPositions(masm_, fun->start_position());
Leon Clarked91b9f72010-01-27 17:25:45 +0000826}
827
828
829void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000830 CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
Leon Clarked91b9f72010-01-27 17:25:45 +0000831}
832
833
834void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 if (!info_->is_debug()) {
836 CodeGenerator::RecordPositions(masm_, stmt->position());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000837 } else {
838 // Check if the statement will be breakable without adding a debug break
839 // slot.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000840 BreakableStatementChecker checker(zone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000841 checker.Check(stmt);
842 // Record the statement position right here if the statement is not
843 // breakable. For breakable statements the actual recording of the
844 // position will be postponed to the breakable code (typically an IC).
845 bool position_recorded = CodeGenerator::RecordPositions(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846 masm_, stmt->position(), !checker.is_breakable());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000847 // If the position recording did record a new position generate a debug
848 // break slot to make the statement breakable.
849 if (position_recorded) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000850 DebugCodegen::GenerateSlot(masm_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000851 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100852 }
853}
854
855
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000856void FullCodeGenerator::VisitSuperReference(SuperReference* super) {
857 __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
858}
859
860
861void FullCodeGenerator::SetExpressionPosition(Expression* expr) {
862 if (!info_->is_debug()) {
863 CodeGenerator::RecordPositions(masm_, expr->position());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000864 } else {
865 // Check if the expression will be breakable without adding a debug break
866 // slot.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000867 BreakableStatementChecker checker(zone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000868 checker.Check(expr);
869 // Record a statement position right here if the expression is not
870 // breakable. For breakable expressions the actual recording of the
871 // position will be postponed to the breakable code (typically an IC).
872 // NOTE this will record a statement position for something which might
873 // not be a statement. As stepping in the debugger will only stop at
874 // statement positions this is used for e.g. the condition expression of
875 // a do while loop.
876 bool position_recorded = CodeGenerator::RecordPositions(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000877 masm_, expr->position(), !checker.is_breakable());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000878 // If the position recording did record a new position generate a debug
879 // break slot to make the statement breakable.
880 if (position_recorded) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000881 DebugCodegen::GenerateSlot(masm_);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000882 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000883 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000884}
885
886
Ben Murdochb0fe1622011-05-05 13:52:32 +0100887void FullCodeGenerator::SetSourcePosition(int pos) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000888 if (pos != RelocInfo::kNoPosition) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100889 masm_->positions_recorder()->RecordPosition(pos);
Leon Clarked91b9f72010-01-27 17:25:45 +0000890 }
891}
892
893
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100894// Lookup table for code generators for special runtime calls which are
895// generated inline.
896#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
897 &FullCodeGenerator::Emit##Name,
Steve Block791712a2010-08-27 10:21:07 +0100898
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100899const FullCodeGenerator::InlineFunctionGenerator
900 FullCodeGenerator::kInlineFunctionGenerators[] = {
901 INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100902 };
903#undef INLINE_FUNCTION_GENERATOR_ADDRESS
904
905
906FullCodeGenerator::InlineFunctionGenerator
907 FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100908 int lookup_index =
909 static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910 DCHECK(lookup_index >= 0);
911 DCHECK(static_cast<size_t>(lookup_index) <
912 arraysize(kInlineFunctionGenerators));
Ben Murdochb0fe1622011-05-05 13:52:32 +0100913 return kInlineFunctionGenerators[lookup_index];
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100914}
915
916
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100917void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
918 const Runtime::Function* function = expr->function();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000919 DCHECK(function != NULL);
920 DCHECK(function->intrinsic_type == Runtime::INLINE);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100921 InlineFunctionGenerator generator =
922 FindInlineFunctionGenerator(function->function_id);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100923 ((*this).*(generator))(expr);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100924}
925
926
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000927void FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) {
928 ZoneList<Expression*>* args = expr->arguments();
929 DCHECK(args->length() == 2);
930 EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::NEXT);
931}
932
933
934void FullCodeGenerator::EmitGeneratorThrow(CallRuntime* expr) {
935 ZoneList<Expression*>* args = expr->arguments();
936 DCHECK(args->length() == 2);
937 EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::THROW);
938}
939
940
941void FullCodeGenerator::EmitDebugBreakInOptimizedCode(CallRuntime* expr) {
942 context()->Plug(handle(Smi::FromInt(0), isolate()));
943}
944
945
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100946void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000947 switch (expr->op()) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100948 case Token::COMMA:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000949 return VisitComma(expr);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100950 case Token::OR:
951 case Token::AND:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000952 return VisitLogicalExpression(expr);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100953 default:
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000954 return VisitArithmeticExpression(expr);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100955 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100956}
957
958
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100959void FullCodeGenerator::VisitInDuplicateContext(Expression* expr) {
960 if (context()->IsEffect()) {
961 VisitForEffect(expr);
962 } else if (context()->IsAccumulatorValue()) {
963 VisitForAccumulatorValue(expr);
964 } else if (context()->IsStackValue()) {
965 VisitForStackValue(expr);
966 } else if (context()->IsTest()) {
967 const TestContext* test = TestContext::cast(context());
968 VisitForControl(expr, test->true_label(), test->false_label(),
969 test->fall_through());
970 }
971}
972
973
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000974void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
975 Comment cmnt(masm_, "[ Comma");
976 VisitForEffect(expr->left());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100977 VisitInDuplicateContext(expr->right());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000978}
Leon Clarked91b9f72010-01-27 17:25:45 +0000979
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000980
981void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
982 bool is_logical_and = expr->op() == Token::AND;
983 Comment cmnt(masm_, is_logical_and ? "[ Logical AND" : "[ Logical OR");
984 Expression* left = expr->left();
985 Expression* right = expr->right();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000986 BailoutId right_id = expr->RightId();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000987 Label done;
988
989 if (context()->IsTest()) {
990 Label eval_right;
991 const TestContext* test = TestContext::cast(context());
992 if (is_logical_and) {
993 VisitForControl(left, &eval_right, test->false_label(), &eval_right);
994 } else {
995 VisitForControl(left, test->true_label(), &eval_right, &eval_right);
996 }
997 PrepareForBailoutForId(right_id, NO_REGISTERS);
998 __ bind(&eval_right);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000999
1000 } else if (context()->IsAccumulatorValue()) {
1001 VisitForAccumulatorValue(left);
1002 // We want the value in the accumulator for the test, and on the stack in
1003 // case we need it.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004 __ Push(result_register());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001005 Label discard, restore;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001006 if (is_logical_and) {
1007 DoTest(left, &discard, &restore, &restore);
1008 } else {
1009 DoTest(left, &restore, &discard, &restore);
1010 }
1011 __ bind(&restore);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001012 __ Pop(result_register());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001013 __ jmp(&done);
1014 __ bind(&discard);
1015 __ Drop(1);
1016 PrepareForBailoutForId(right_id, NO_REGISTERS);
1017
1018 } else if (context()->IsStackValue()) {
1019 VisitForAccumulatorValue(left);
1020 // We want the value in the accumulator for the test, and on the stack in
1021 // case we need it.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001022 __ Push(result_register());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001023 Label discard;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001024 if (is_logical_and) {
1025 DoTest(left, &discard, &done, &discard);
1026 } else {
1027 DoTest(left, &done, &discard, &discard);
1028 }
1029 __ bind(&discard);
1030 __ Drop(1);
1031 PrepareForBailoutForId(right_id, NO_REGISTERS);
1032
1033 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001034 DCHECK(context()->IsEffect());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001035 Label eval_right;
1036 if (is_logical_and) {
1037 VisitForControl(left, &eval_right, &done, &eval_right);
1038 } else {
1039 VisitForControl(left, &done, &eval_right, &eval_right);
1040 }
1041 PrepareForBailoutForId(right_id, NO_REGISTERS);
1042 __ bind(&eval_right);
1043 }
1044
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001045 VisitInDuplicateContext(right);
Leon Clarked91b9f72010-01-27 17:25:45 +00001046 __ bind(&done);
1047}
1048
1049
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001050void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
1051 Token::Value op = expr->op();
1052 Comment cmnt(masm_, "[ ArithmeticExpression");
1053 Expression* left = expr->left();
1054 Expression* right = expr->right();
1055 OverwriteMode mode =
1056 left->ResultOverwriteAllowed()
1057 ? OVERWRITE_LEFT
1058 : (right->ResultOverwriteAllowed() ? OVERWRITE_RIGHT : NO_OVERWRITE);
1059
1060 VisitForStackValue(left);
1061 VisitForAccumulatorValue(right);
1062
1063 SetSourcePosition(expr->position());
1064 if (ShouldInlineSmiCase(op)) {
1065 EmitInlineSmiBinaryOp(expr, op, mode, left, right);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001066 } else {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001067 EmitBinaryOp(expr, op, mode);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001068 }
1069}
1070
1071
Leon Clarked91b9f72010-01-27 17:25:45 +00001072void FullCodeGenerator::VisitBlock(Block* stmt) {
1073 Comment cmnt(masm_, "[ Block");
Ben Murdoch589d6972011-11-30 16:04:58 +00001074 NestedBlock nested_block(this, stmt);
Leon Clarked91b9f72010-01-27 17:25:45 +00001075 SetStatementPosition(stmt);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001076
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001077 {
1078 EnterBlockScopeIfNeeded block_scope_state(
1079 this, stmt->scope(), stmt->EntryId(), stmt->DeclsId(), stmt->ExitId());
1080 VisitStatements(stmt->statements());
1081 __ bind(nested_block.break_label());
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001082 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001083}
1084
1085
1086void FullCodeGenerator::VisitModuleStatement(ModuleStatement* stmt) {
1087 Comment cmnt(masm_, "[ Module context");
1088
1089 __ Push(Smi::FromInt(stmt->proxy()->interface()->Index()));
1090 __ Push(Smi::FromInt(0));
1091 __ CallRuntime(Runtime::kPushModuleContext, 2);
1092 StoreToFrameField(
1093 StandardFrameConstants::kContextOffset, context_register());
1094
1095 Scope* saved_scope = scope_;
1096 scope_ = stmt->body()->scope();
1097 VisitStatements(stmt->body()->statements());
1098 scope_ = saved_scope;
1099 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1100 // Update local stack frame context field.
1101 StoreToFrameField(StandardFrameConstants::kContextOffset,
1102 context_register());
Leon Clarked91b9f72010-01-27 17:25:45 +00001103}
1104
1105
1106void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
1107 Comment cmnt(masm_, "[ ExpressionStatement");
1108 SetStatementPosition(stmt);
1109 VisitForEffect(stmt->expression());
1110}
1111
1112
1113void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
1114 Comment cmnt(masm_, "[ EmptyStatement");
1115 SetStatementPosition(stmt);
1116}
1117
1118
1119void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
1120 Comment cmnt(masm_, "[ IfStatement");
1121 SetStatementPosition(stmt);
1122 Label then_part, else_part, done;
1123
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001124 if (stmt->HasElseStatement()) {
1125 VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001126 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001127 __ bind(&then_part);
1128 Visit(stmt->then_statement());
1129 __ jmp(&done);
Leon Clarked91b9f72010-01-27 17:25:45 +00001130
Ben Murdochb0fe1622011-05-05 13:52:32 +01001131 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001132 __ bind(&else_part);
1133 Visit(stmt->else_statement());
1134 } else {
1135 VisitForControl(stmt->condition(), &then_part, &done, &then_part);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001136 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001137 __ bind(&then_part);
1138 Visit(stmt->then_statement());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001139
1140 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001141 }
Leon Clarked91b9f72010-01-27 17:25:45 +00001142 __ bind(&done);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001143 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
Leon Clarked91b9f72010-01-27 17:25:45 +00001144}
1145
1146
1147void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
1148 Comment cmnt(masm_, "[ ContinueStatement");
1149 SetStatementPosition(stmt);
1150 NestedStatement* current = nesting_stack_;
1151 int stack_depth = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001152 int context_length = 0;
Ben Murdochdb5a90a2011-01-06 18:27:03 +00001153 // When continuing, we clobber the unpredictable value in the accumulator
1154 // with one that's safe for GC. If we hit an exit from the try block of
1155 // try...finally on our way out, we will unconditionally preserve the
1156 // accumulator on the stack.
1157 ClearAccumulator();
Leon Clarked91b9f72010-01-27 17:25:45 +00001158 while (!current->IsContinueTarget(stmt->target())) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001159 current = current->Exit(&stack_depth, &context_length);
Leon Clarked91b9f72010-01-27 17:25:45 +00001160 }
1161 __ Drop(stack_depth);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001162 if (context_length > 0) {
1163 while (context_length > 0) {
1164 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1165 --context_length;
1166 }
1167 StoreToFrameField(StandardFrameConstants::kContextOffset,
1168 context_register());
1169 }
Leon Clarked91b9f72010-01-27 17:25:45 +00001170
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001171 __ jmp(current->AsIteration()->continue_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001172}
1173
1174
1175void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
1176 Comment cmnt(masm_, "[ BreakStatement");
1177 SetStatementPosition(stmt);
1178 NestedStatement* current = nesting_stack_;
1179 int stack_depth = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001180 int context_length = 0;
Ben Murdochdb5a90a2011-01-06 18:27:03 +00001181 // When breaking, we clobber the unpredictable value in the accumulator
1182 // with one that's safe for GC. If we hit an exit from the try block of
1183 // try...finally on our way out, we will unconditionally preserve the
1184 // accumulator on the stack.
1185 ClearAccumulator();
Leon Clarked91b9f72010-01-27 17:25:45 +00001186 while (!current->IsBreakTarget(stmt->target())) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001187 current = current->Exit(&stack_depth, &context_length);
Leon Clarked91b9f72010-01-27 17:25:45 +00001188 }
1189 __ Drop(stack_depth);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001190 if (context_length > 0) {
1191 while (context_length > 0) {
1192 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1193 --context_length;
1194 }
1195 StoreToFrameField(StandardFrameConstants::kContextOffset,
1196 context_register());
1197 }
Leon Clarked91b9f72010-01-27 17:25:45 +00001198
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001199 __ jmp(current->AsBreakable()->break_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001200}
1201
1202
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001203void FullCodeGenerator::EmitUnwindBeforeReturn() {
Leon Clarked91b9f72010-01-27 17:25:45 +00001204 NestedStatement* current = nesting_stack_;
1205 int stack_depth = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001206 int context_length = 0;
Leon Clarked91b9f72010-01-27 17:25:45 +00001207 while (current != NULL) {
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001208 current = current->Exit(&stack_depth, &context_length);
Leon Clarked91b9f72010-01-27 17:25:45 +00001209 }
1210 __ Drop(stack_depth);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001211}
Leon Clarked91b9f72010-01-27 17:25:45 +00001212
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001213
1214void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
1215 Comment cmnt(masm_, "[ ReturnStatement");
1216 SetStatementPosition(stmt);
1217 Expression* expr = stmt->expression();
1218 VisitForAccumulatorValue(expr);
1219 EmitUnwindBeforeReturn();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001220 EmitReturnSequence();
Leon Clarked91b9f72010-01-27 17:25:45 +00001221}
1222
1223
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001224void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
1225 Comment cmnt(masm_, "[ WithStatement");
Leon Clarked91b9f72010-01-27 17:25:45 +00001226 SetStatementPosition(stmt);
1227
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001228 VisitForStackValue(stmt->expression());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001229 PushFunctionArgumentForContextAllocation();
1230 __ CallRuntime(Runtime::kPushWithContext, 2);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001231 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1232
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001233 Scope* saved_scope = scope();
1234 scope_ = stmt->scope();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001235 { WithOrCatch body(this);
1236 Visit(stmt->statement());
1237 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001238 scope_ = saved_scope;
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001239
1240 // Pop context.
1241 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1242 // Update local stack frame context field.
Leon Clarked91b9f72010-01-27 17:25:45 +00001243 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1244}
1245
1246
Leon Clarked91b9f72010-01-27 17:25:45 +00001247void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
1248 Comment cmnt(masm_, "[ DoWhileStatement");
1249 SetStatementPosition(stmt);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001250 Label body, book_keeping;
Leon Clarked91b9f72010-01-27 17:25:45 +00001251
1252 Iteration loop_statement(this, stmt);
1253 increment_loop_depth();
1254
1255 __ bind(&body);
1256 Visit(stmt->body());
1257
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001258 // Record the position of the do while condition and make sure it is
1259 // possible to break on the condition.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001260 __ bind(loop_statement.continue_label());
Ben Murdochb0fe1622011-05-05 13:52:32 +01001261 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001262 SetExpressionPosition(stmt->cond());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001263 VisitForControl(stmt->cond(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264 &book_keeping,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001265 loop_statement.break_label(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001266 &book_keeping);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001267
Ben Murdochb0fe1622011-05-05 13:52:32 +01001268 // Check stack before looping.
1269 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001270 __ bind(&book_keeping);
1271 EmitBackEdgeBookkeeping(stmt, &body);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001272 __ jmp(&body);
1273
1274 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001275 __ bind(loop_statement.break_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001276 decrement_loop_depth();
1277}
1278
1279
1280void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1281 Comment cmnt(masm_, "[ WhileStatement");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001282 Label loop, body;
Leon Clarked91b9f72010-01-27 17:25:45 +00001283
1284 Iteration loop_statement(this, stmt);
1285 increment_loop_depth();
1286
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001287 __ bind(&loop);
1288
1289 SetExpressionPosition(stmt->cond());
1290 VisitForControl(stmt->cond(),
1291 &body,
1292 loop_statement.break_label(),
1293 &body);
Leon Clarked91b9f72010-01-27 17:25:45 +00001294
Ben Murdochb0fe1622011-05-05 13:52:32 +01001295 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
Leon Clarked91b9f72010-01-27 17:25:45 +00001296 __ bind(&body);
1297 Visit(stmt->body());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001298
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001299 __ bind(loop_statement.continue_label());
Leon Clarkef7060e22010-06-03 12:02:55 +01001300
Leon Clarked91b9f72010-01-27 17:25:45 +00001301 // Check stack before looping.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001302 EmitBackEdgeBookkeeping(stmt, &loop);
1303 __ jmp(&loop);
Leon Clarked91b9f72010-01-27 17:25:45 +00001304
Ben Murdochb0fe1622011-05-05 13:52:32 +01001305 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001306 __ bind(loop_statement.break_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001307 decrement_loop_depth();
1308}
1309
1310
1311void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
1312 Comment cmnt(masm_, "[ ForStatement");
Ben Murdochb0fe1622011-05-05 13:52:32 +01001313 Label test, body;
Leon Clarked91b9f72010-01-27 17:25:45 +00001314
1315 Iteration loop_statement(this, stmt);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001316
1317 // Set statement position for a break slot before entering the for-body.
1318 SetStatementPosition(stmt);
1319
Leon Clarked91b9f72010-01-27 17:25:45 +00001320 if (stmt->init() != NULL) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001321 SetStatementPosition(stmt->init());
Leon Clarked91b9f72010-01-27 17:25:45 +00001322 Visit(stmt->init());
1323 }
1324
1325 increment_loop_depth();
1326 // Emit the test at the bottom of the loop (even if empty).
1327 __ jmp(&test);
1328
Ben Murdochb0fe1622011-05-05 13:52:32 +01001329 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
Leon Clarked91b9f72010-01-27 17:25:45 +00001330 __ bind(&body);
1331 Visit(stmt->body());
1332
Ben Murdochb0fe1622011-05-05 13:52:32 +01001333 PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001334 __ bind(loop_statement.continue_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001335 if (stmt->next() != NULL) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001336 SetStatementPosition(stmt->next());
Leon Clarked91b9f72010-01-27 17:25:45 +00001337 Visit(stmt->next());
1338 }
1339
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001340 // Emit the statement position here as this is where the for
1341 // statement code starts.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001342 SetStatementPosition(stmt);
Leon Clarked91b9f72010-01-27 17:25:45 +00001343
1344 // Check stack before looping.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001345 EmitBackEdgeBookkeeping(stmt, &body);
Leon Clarked91b9f72010-01-27 17:25:45 +00001346
Ben Murdochb0fe1622011-05-05 13:52:32 +01001347 __ bind(&test);
Leon Clarked91b9f72010-01-27 17:25:45 +00001348 if (stmt->cond() != NULL) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001349 SetExpressionPosition(stmt->cond());
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001350 VisitForControl(stmt->cond(),
1351 &body,
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001352 loop_statement.break_label(),
1353 loop_statement.break_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001354 } else {
1355 __ jmp(&body);
1356 }
1357
Ben Murdochb0fe1622011-05-05 13:52:32 +01001358 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001359 __ bind(loop_statement.break_label());
Leon Clarked91b9f72010-01-27 17:25:45 +00001360 decrement_loop_depth();
1361}
1362
1363
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001364void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1365 Comment cmnt(masm_, "[ ForOfStatement");
1366 SetStatementPosition(stmt);
1367
1368 Iteration loop_statement(this, stmt);
1369 increment_loop_depth();
1370
1371 // var iterator = iterable[Symbol.iterator]();
1372 VisitForEffect(stmt->assign_iterator());
1373
1374 // Loop entry.
1375 __ bind(loop_statement.continue_label());
1376
1377 // result = iterator.next()
1378 SetExpressionPosition(stmt->next_result());
1379 VisitForEffect(stmt->next_result());
1380
1381 // if (result.done) break;
1382 Label result_not_done;
1383 VisitForControl(stmt->result_done(), loop_statement.break_label(),
1384 &result_not_done, &result_not_done);
1385 __ bind(&result_not_done);
1386
1387 // each = result.value
1388 VisitForEffect(stmt->assign_each());
1389
1390 // Generate code for the body of the loop.
1391 Visit(stmt->body());
1392
1393 // Check stack before looping.
1394 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
1395 EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
1396 __ jmp(loop_statement.continue_label());
1397
1398 // Exit and decrement the loop depth.
1399 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1400 __ bind(loop_statement.break_label());
1401 decrement_loop_depth();
1402}
1403
1404
Leon Clarked91b9f72010-01-27 17:25:45 +00001405void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1406 Comment cmnt(masm_, "[ TryCatchStatement");
1407 SetStatementPosition(stmt);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001408 // The try block adds a handler to the exception handler chain before
1409 // entering, and removes it again when exiting normally. If an exception
1410 // is thrown during execution of the try block, the handler is consumed
1411 // and control is passed to the catch block with the exception in the
1412 // result register.
Leon Clarked91b9f72010-01-27 17:25:45 +00001413
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001414 Label try_entry, handler_entry, exit;
1415 __ jmp(&try_entry);
1416 __ bind(&handler_entry);
1417 handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
1418 // Exception handler code, the exception is in the result register.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001419 // Extend the context before executing the catch block.
1420 { Comment cmnt(masm_, "[ Extend catch context");
1421 __ Push(stmt->variable()->name());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001422 __ Push(result_register());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001423 PushFunctionArgumentForContextAllocation();
1424 __ CallRuntime(Runtime::kPushCatchContext, 3);
1425 StoreToFrameField(StandardFrameConstants::kContextOffset,
1426 context_register());
Leon Clarked91b9f72010-01-27 17:25:45 +00001427 }
1428
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001429 Scope* saved_scope = scope();
1430 scope_ = stmt->scope();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001431 DCHECK(scope_->declarations()->is_empty());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001432 { WithOrCatch catch_body(this);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001433 Visit(stmt->catch_block());
1434 }
Ben Murdoch589d6972011-11-30 16:04:58 +00001435 // Restore the context.
1436 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1437 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001438 scope_ = saved_scope;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001439 __ jmp(&exit);
Leon Clarked91b9f72010-01-27 17:25:45 +00001440
1441 // Try block code. Sets up the exception handler chain.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001442 __ bind(&try_entry);
1443 __ PushTryHandler(StackHandler::CATCH, stmt->index());
1444 { TryCatch try_body(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001445 Visit(stmt->try_block());
Leon Clarked91b9f72010-01-27 17:25:45 +00001446 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001447 __ PopTryHandler();
1448 __ bind(&exit);
Leon Clarked91b9f72010-01-27 17:25:45 +00001449}
1450
1451
1452void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1453 Comment cmnt(masm_, "[ TryFinallyStatement");
1454 SetStatementPosition(stmt);
1455 // Try finally is compiled by setting up a try-handler on the stack while
1456 // executing the try body, and removing it again afterwards.
1457 //
1458 // The try-finally construct can enter the finally block in three ways:
1459 // 1. By exiting the try-block normally. This removes the try-handler and
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001460 // calls the finally block code before continuing.
Leon Clarked91b9f72010-01-27 17:25:45 +00001461 // 2. By exiting the try-block with a function-local control flow transfer
1462 // (break/continue/return). The site of the, e.g., break removes the
1463 // try handler and calls the finally block code before continuing
1464 // its outward control transfer.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001465 // 3. By exiting the try-block with a thrown exception.
Leon Clarked91b9f72010-01-27 17:25:45 +00001466 // This can happen in nested function calls. It traverses the try-handler
1467 // chain and consumes the try-handler entry before jumping to the
1468 // handler code. The handler code then calls the finally-block before
1469 // rethrowing the exception.
1470 //
1471 // The finally block must assume a return address on top of the stack
1472 // (or in the link register on ARM chips) and a value (return value or
1473 // exception) in the result register (rax/eax/r0), both of which must
1474 // be preserved. The return address isn't GC-safe, so it should be
1475 // cooked before GC.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001476 Label try_entry, handler_entry, finally_entry;
Leon Clarked91b9f72010-01-27 17:25:45 +00001477
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001478 // Jump to try-handler setup and try-block code.
1479 __ jmp(&try_entry);
1480 __ bind(&handler_entry);
1481 handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
1482 // Exception handler code. This code is only executed when an exception
1483 // is thrown. The exception is in the result register, and must be
1484 // preserved by the finally block. Call the finally block and then
1485 // rethrow the exception if it returns.
1486 __ Call(&finally_entry);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001487 __ Push(result_register());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001488 __ CallRuntime(Runtime::kReThrow, 1);
Leon Clarked91b9f72010-01-27 17:25:45 +00001489
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001490 // Finally block implementation.
Leon Clarked91b9f72010-01-27 17:25:45 +00001491 __ bind(&finally_entry);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001492 EnterFinallyBlock();
1493 { Finally finally_body(this);
Leon Clarked91b9f72010-01-27 17:25:45 +00001494 Visit(stmt->finally_block());
Leon Clarked91b9f72010-01-27 17:25:45 +00001495 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001496 ExitFinallyBlock(); // Return to the calling code.
Leon Clarked91b9f72010-01-27 17:25:45 +00001497
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001498 // Set up try handler.
1499 __ bind(&try_entry);
1500 __ PushTryHandler(StackHandler::FINALLY, stmt->index());
1501 { TryFinally try_body(this, &finally_entry);
Leon Clarked91b9f72010-01-27 17:25:45 +00001502 Visit(stmt->try_block());
Leon Clarked91b9f72010-01-27 17:25:45 +00001503 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001504 __ PopTryHandler();
Ben Murdochdb5a90a2011-01-06 18:27:03 +00001505 // Execute the finally block on the way out. Clobber the unpredictable
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001506 // value in the result register with one that's safe for GC because the
1507 // finally block will unconditionally preserve the result register on the
1508 // stack.
Ben Murdochdb5a90a2011-01-06 18:27:03 +00001509 ClearAccumulator();
Leon Clarked91b9f72010-01-27 17:25:45 +00001510 __ Call(&finally_entry);
1511}
1512
1513
1514void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
Leon Clarked91b9f72010-01-27 17:25:45 +00001515 Comment cmnt(masm_, "[ DebuggerStatement");
1516 SetStatementPosition(stmt);
Leon Clarke4515c472010-02-03 11:58:03 +00001517
Andrei Popescu402d9372010-02-26 13:31:12 +00001518 __ DebugBreak();
Leon Clarked91b9f72010-01-27 17:25:45 +00001519 // Ignore the return value.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001520
1521 PrepareForBailoutForId(stmt->DebugBreakId(), NO_REGISTERS);
1522}
1523
1524
1525void FullCodeGenerator::VisitCaseClause(CaseClause* clause) {
1526 UNREACHABLE();
Leon Clarked91b9f72010-01-27 17:25:45 +00001527}
1528
1529
Leon Clarked91b9f72010-01-27 17:25:45 +00001530void FullCodeGenerator::VisitConditional(Conditional* expr) {
1531 Comment cmnt(masm_, "[ Conditional");
1532 Label true_case, false_case, done;
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001533 VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
Leon Clarked91b9f72010-01-27 17:25:45 +00001534
Ben Murdochb0fe1622011-05-05 13:52:32 +01001535 PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
Leon Clarked91b9f72010-01-27 17:25:45 +00001536 __ bind(&true_case);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001537 SetExpressionPosition(expr->then_expression());
Ben Murdochf87a2032010-10-22 12:50:53 +01001538 if (context()->IsTest()) {
1539 const TestContext* for_test = TestContext::cast(context());
1540 VisitForControl(expr->then_expression(),
1541 for_test->true_label(),
1542 for_test->false_label(),
1543 NULL);
1544 } else {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001545 VisitInDuplicateContext(expr->then_expression());
Leon Clarked91b9f72010-01-27 17:25:45 +00001546 __ jmp(&done);
1547 }
1548
Ben Murdochb0fe1622011-05-05 13:52:32 +01001549 PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
Leon Clarked91b9f72010-01-27 17:25:45 +00001550 __ bind(&false_case);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001551 SetExpressionPosition(expr->else_expression());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001552 VisitInDuplicateContext(expr->else_expression());
Leon Clarked91b9f72010-01-27 17:25:45 +00001553 // If control flow falls through Visit, merge it with true case here.
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001554 if (!context()->IsTest()) {
Leon Clarked91b9f72010-01-27 17:25:45 +00001555 __ bind(&done);
1556 }
1557}
1558
1559
Leon Clarked91b9f72010-01-27 17:25:45 +00001560void FullCodeGenerator::VisitLiteral(Literal* expr) {
1561 Comment cmnt(masm_, "[ Literal");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001562 context()->Plug(expr->value());
Leon Clarked91b9f72010-01-27 17:25:45 +00001563}
1564
1565
Leon Clarkef7060e22010-06-03 12:02:55 +01001566void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1567 Comment cmnt(masm_, "[ FunctionLiteral");
1568
1569 // Build the function boilerplate and instantiate it.
1570 Handle<SharedFunctionInfo> function_info =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001571 Compiler::BuildFunctionInfo(expr, script(), info_);
Ben Murdochf87a2032010-10-22 12:50:53 +01001572 if (function_info.is_null()) {
1573 SetStackOverflow();
1574 return;
1575 }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001576 EmitNewClosure(function_info, expr->pretenure());
Leon Clarkef7060e22010-06-03 12:02:55 +01001577}
1578
1579
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001580void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001581 Comment cmnt(masm_, "[ ClassLiteral");
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001582
1583 {
1584 EnterBlockScopeIfNeeded block_scope_state(
1585 this, lit->scope(), BailoutId::None(), BailoutId::None(),
1586 BailoutId::None());
1587
1588 if (lit->raw_name() != NULL) {
1589 __ Push(lit->name());
1590 } else {
1591 __ Push(isolate()->factory()->undefined_value());
1592 }
1593
1594 if (lit->extends() != NULL) {
1595 VisitForStackValue(lit->extends());
1596 } else {
1597 __ Push(isolate()->factory()->the_hole_value());
1598 }
1599
1600 VisitForStackValue(lit->constructor());
1601
1602 __ Push(script());
1603 __ Push(Smi::FromInt(lit->start_position()));
1604 __ Push(Smi::FromInt(lit->end_position()));
1605
1606 __ CallRuntime(Runtime::kDefineClass, 6);
1607 EmitClassDefineProperties(lit);
1608
1609 if (lit->scope() != NULL) {
1610 DCHECK_NOT_NULL(lit->class_variable_proxy());
1611 EmitVariableAssignment(lit->class_variable_proxy()->var(),
1612 Token::INIT_CONST);
1613 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001614 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001615
1616 context()->Plug(result_register());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001617}
1618
1619
1620void FullCodeGenerator::VisitNativeFunctionLiteral(
1621 NativeFunctionLiteral* expr) {
1622 Comment cmnt(masm_, "[ NativeFunctionLiteral");
1623
1624 // Compute the function template for the native function.
1625 Handle<String> name = expr->name();
1626 v8::Handle<v8::FunctionTemplate> fun_template =
1627 expr->extension()->GetNativeFunctionTemplate(
1628 reinterpret_cast<v8::Isolate*>(isolate()), v8::Utils::ToLocal(name));
1629 DCHECK(!fun_template.IsEmpty());
1630
1631 // Instantiate the function and create a shared function info from it.
1632 Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1633 const int literals = fun->NumberOfLiterals();
1634 Handle<Code> code = Handle<Code>(fun->shared()->code());
1635 Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
1636 Handle<SharedFunctionInfo> shared =
1637 isolate()->factory()->NewSharedFunctionInfo(
1638 name, literals, FunctionKind::kNormalFunction, code,
1639 Handle<ScopeInfo>(fun->shared()->scope_info()),
1640 Handle<TypeFeedbackVector>(fun->shared()->feedback_vector()));
1641 shared->set_construct_stub(*construct_stub);
1642
1643 // Copy the function data to the shared function info.
1644 shared->set_function_data(fun->shared()->function_data());
1645 int parameters = fun->shared()->formal_parameter_count();
1646 shared->set_formal_parameter_count(parameters);
1647
1648 EmitNewClosure(shared, false);
Leon Clarkef7060e22010-06-03 12:02:55 +01001649}
1650
1651
Leon Clarked91b9f72010-01-27 17:25:45 +00001652void FullCodeGenerator::VisitThrow(Throw* expr) {
1653 Comment cmnt(masm_, "[ Throw");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001654 VisitForStackValue(expr->exception());
Leon Clarked91b9f72010-01-27 17:25:45 +00001655 __ CallRuntime(Runtime::kThrow, 1);
1656 // Never returns here.
1657}
1658
1659
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001660FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
1661 int* stack_depth,
1662 int* context_length) {
Leon Clarked91b9f72010-01-27 17:25:45 +00001663 // The macros used here must preserve the result register.
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001664 __ Drop(*stack_depth);
Leon Clarked91b9f72010-01-27 17:25:45 +00001665 __ PopTryHandler();
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001666 *stack_depth = 0;
1667 return previous_;
Leon Clarked91b9f72010-01-27 17:25:45 +00001668}
1669
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001670
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001671bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
1672 Expression* sub_expr;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001673 Handle<String> check;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001674 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
1675 EmitLiteralCompareTypeof(expr, sub_expr, check);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001676 return true;
1677 }
1678
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001679 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001680 EmitLiteralCompareNil(expr, sub_expr, kUndefinedValue);
1681 return true;
1682 }
1683
1684 if (expr->IsLiteralCompareNull(&sub_expr)) {
1685 EmitLiteralCompareNil(expr, sub_expr, kNullValue);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001686 return true;
1687 }
1688
1689 return false;
1690}
1691
1692
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001693void BackEdgeTable::Patch(Isolate* isolate, Code* unoptimized) {
1694 DisallowHeapAllocation no_gc;
1695 Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement);
1696
1697 // Increment loop nesting level by one and iterate over the back edge table
1698 // to find the matching loops to patch the interrupt
1699 // call to an unconditional call to the replacement code.
1700 int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level() + 1;
1701 if (loop_nesting_level > Code::kMaxLoopNestingMarker) return;
1702
1703 BackEdgeTable back_edges(unoptimized, &no_gc);
1704 for (uint32_t i = 0; i < back_edges.length(); i++) {
1705 if (static_cast<int>(back_edges.loop_depth(i)) == loop_nesting_level) {
1706 DCHECK_EQ(INTERRUPT, GetBackEdgeState(isolate,
1707 unoptimized,
1708 back_edges.pc(i)));
1709 PatchAt(unoptimized, back_edges.pc(i), ON_STACK_REPLACEMENT, patch);
1710 }
1711 }
1712
1713 unoptimized->set_allow_osr_at_loop_nesting_level(loop_nesting_level);
1714 DCHECK(Verify(isolate, unoptimized));
1715}
1716
1717
1718void BackEdgeTable::Revert(Isolate* isolate, Code* unoptimized) {
1719 DisallowHeapAllocation no_gc;
1720 Code* patch = isolate->builtins()->builtin(Builtins::kInterruptCheck);
1721
1722 // Iterate over the back edge table and revert the patched interrupt calls.
1723 int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
1724
1725 BackEdgeTable back_edges(unoptimized, &no_gc);
1726 for (uint32_t i = 0; i < back_edges.length(); i++) {
1727 if (static_cast<int>(back_edges.loop_depth(i)) <= loop_nesting_level) {
1728 DCHECK_NE(INTERRUPT, GetBackEdgeState(isolate,
1729 unoptimized,
1730 back_edges.pc(i)));
1731 PatchAt(unoptimized, back_edges.pc(i), INTERRUPT, patch);
1732 }
1733 }
1734
1735 unoptimized->set_allow_osr_at_loop_nesting_level(0);
1736 // Assert that none of the back edges are patched anymore.
1737 DCHECK(Verify(isolate, unoptimized));
1738}
1739
1740
1741void BackEdgeTable::AddStackCheck(Handle<Code> code, uint32_t pc_offset) {
1742 DisallowHeapAllocation no_gc;
1743 Isolate* isolate = code->GetIsolate();
1744 Address pc = code->instruction_start() + pc_offset;
1745 Code* patch = isolate->builtins()->builtin(Builtins::kOsrAfterStackCheck);
1746 PatchAt(*code, pc, OSR_AFTER_STACK_CHECK, patch);
1747}
1748
1749
1750void BackEdgeTable::RemoveStackCheck(Handle<Code> code, uint32_t pc_offset) {
1751 DisallowHeapAllocation no_gc;
1752 Isolate* isolate = code->GetIsolate();
1753 Address pc = code->instruction_start() + pc_offset;
1754
1755 if (OSR_AFTER_STACK_CHECK == GetBackEdgeState(isolate, *code, pc)) {
1756 Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement);
1757 PatchAt(*code, pc, ON_STACK_REPLACEMENT, patch);
1758 }
1759}
1760
1761
1762#ifdef DEBUG
1763bool BackEdgeTable::Verify(Isolate* isolate, Code* unoptimized) {
1764 DisallowHeapAllocation no_gc;
1765 int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
1766 BackEdgeTable back_edges(unoptimized, &no_gc);
1767 for (uint32_t i = 0; i < back_edges.length(); i++) {
1768 uint32_t loop_depth = back_edges.loop_depth(i);
1769 CHECK_LE(static_cast<int>(loop_depth), Code::kMaxLoopNestingMarker);
1770 // Assert that all back edges for shallower loops (and only those)
1771 // have already been patched.
1772 CHECK_EQ((static_cast<int>(loop_depth) <= loop_nesting_level),
1773 GetBackEdgeState(isolate,
1774 unoptimized,
1775 back_edges.pc(i)) != INTERRUPT);
1776 }
1777 return true;
1778}
1779#endif // DEBUG
1780
1781
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001782FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded(
1783 FullCodeGenerator* codegen, Scope* scope, BailoutId entry_id,
1784 BailoutId declarations_id, BailoutId exit_id)
1785 : codegen_(codegen), scope_(scope), exit_id_(exit_id) {
1786 saved_scope_ = codegen_->scope();
1787
1788 if (scope == NULL) {
1789 codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS);
1790 } else {
1791 codegen_->scope_ = scope;
1792 {
1793 Comment cmnt(masm(), "[ Extend block context");
1794 __ Push(scope->GetScopeInfo());
1795 codegen_->PushFunctionArgumentForContextAllocation();
1796 __ CallRuntime(Runtime::kPushBlockContext, 2);
1797
1798 // Replace the context stored in the frame.
1799 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
1800 codegen_->context_register());
1801 codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS);
1802 }
1803 {
1804 Comment cmnt(masm(), "[ Declarations");
1805 codegen_->VisitDeclarations(scope->declarations());
1806 codegen_->PrepareForBailoutForId(declarations_id, NO_REGISTERS);
1807 }
1808 }
1809}
1810
1811
1812FullCodeGenerator::EnterBlockScopeIfNeeded::~EnterBlockScopeIfNeeded() {
1813 if (scope_ != NULL) {
1814 codegen_->LoadContextField(codegen_->context_register(),
1815 Context::PREVIOUS_INDEX);
1816 // Update local stack frame context field.
1817 codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
1818 codegen_->context_register());
1819 }
1820 codegen_->PrepareForBailoutForId(exit_id_, NO_REGISTERS);
1821 codegen_->scope_ = saved_scope_;
1822}
1823
1824
Leon Clarked91b9f72010-01-27 17:25:45 +00001825#undef __
1826
1827
1828} } // namespace v8::internal