• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "codegen.h"
31 #include "compiler.h"
32 #include "debug.h"
33 #include "full-codegen.h"
34 #include "liveedit.h"
35 #include "macro-assembler.h"
36 #include "prettyprinter.h"
37 #include "scopes.h"
38 #include "scopeinfo.h"
39 #include "stub-cache.h"
40 
41 namespace v8 {
42 namespace internal {
43 
Check(Statement * stmt)44 void BreakableStatementChecker::Check(Statement* stmt) {
45   Visit(stmt);
46 }
47 
48 
Check(Expression * expr)49 void BreakableStatementChecker::Check(Expression* expr) {
50   Visit(expr);
51 }
52 
53 
VisitVariableDeclaration(VariableDeclaration * decl)54 void BreakableStatementChecker::VisitVariableDeclaration(
55     VariableDeclaration* decl) {
56 }
57 
VisitFunctionDeclaration(FunctionDeclaration * decl)58 void BreakableStatementChecker::VisitFunctionDeclaration(
59     FunctionDeclaration* decl) {
60 }
61 
VisitModuleDeclaration(ModuleDeclaration * decl)62 void BreakableStatementChecker::VisitModuleDeclaration(
63     ModuleDeclaration* decl) {
64 }
65 
VisitImportDeclaration(ImportDeclaration * decl)66 void BreakableStatementChecker::VisitImportDeclaration(
67     ImportDeclaration* decl) {
68 }
69 
VisitExportDeclaration(ExportDeclaration * decl)70 void BreakableStatementChecker::VisitExportDeclaration(
71     ExportDeclaration* decl) {
72 }
73 
74 
VisitModuleLiteral(ModuleLiteral * module)75 void BreakableStatementChecker::VisitModuleLiteral(ModuleLiteral* module) {
76 }
77 
VisitModuleVariable(ModuleVariable * module)78 void BreakableStatementChecker::VisitModuleVariable(ModuleVariable* module) {
79 }
80 
VisitModulePath(ModulePath * module)81 void BreakableStatementChecker::VisitModulePath(ModulePath* module) {
82 }
83 
VisitModuleUrl(ModuleUrl * module)84 void BreakableStatementChecker::VisitModuleUrl(ModuleUrl* module) {
85 }
86 
87 
VisitBlock(Block * stmt)88 void BreakableStatementChecker::VisitBlock(Block* stmt) {
89 }
90 
91 
VisitExpressionStatement(ExpressionStatement * stmt)92 void BreakableStatementChecker::VisitExpressionStatement(
93     ExpressionStatement* stmt) {
94   // Check if expression is breakable.
95   Visit(stmt->expression());
96 }
97 
98 
VisitEmptyStatement(EmptyStatement * stmt)99 void BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) {
100 }
101 
102 
VisitIfStatement(IfStatement * stmt)103 void BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) {
104   // If the condition is breakable the if statement is breakable.
105   Visit(stmt->condition());
106 }
107 
108 
VisitContinueStatement(ContinueStatement * stmt)109 void BreakableStatementChecker::VisitContinueStatement(
110     ContinueStatement* stmt) {
111 }
112 
113 
VisitBreakStatement(BreakStatement * stmt)114 void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
115 }
116 
117 
VisitReturnStatement(ReturnStatement * stmt)118 void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
119   // Return is breakable if the expression is.
120   Visit(stmt->expression());
121 }
122 
123 
VisitWithStatement(WithStatement * stmt)124 void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) {
125   Visit(stmt->expression());
126 }
127 
128 
VisitSwitchStatement(SwitchStatement * stmt)129 void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
130   // Switch statements breakable if the tag expression is.
131   Visit(stmt->tag());
132 }
133 
134 
VisitDoWhileStatement(DoWhileStatement * stmt)135 void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
136   // Mark do while as breakable to avoid adding a break slot in front of it.
137   is_breakable_ = true;
138 }
139 
140 
VisitWhileStatement(WhileStatement * stmt)141 void BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) {
142   // Mark while statements breakable if the condition expression is.
143   Visit(stmt->cond());
144 }
145 
146 
VisitForStatement(ForStatement * stmt)147 void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
148   // Mark for statements breakable if the condition expression is.
149   if (stmt->cond() != NULL) {
150     Visit(stmt->cond());
151   }
152 }
153 
154 
VisitForInStatement(ForInStatement * stmt)155 void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
156   // Mark for in statements breakable if the enumerable expression is.
157   Visit(stmt->enumerable());
158 }
159 
160 
VisitTryCatchStatement(TryCatchStatement * stmt)161 void BreakableStatementChecker::VisitTryCatchStatement(
162     TryCatchStatement* stmt) {
163   // Mark try catch as breakable to avoid adding a break slot in front of it.
164   is_breakable_ = true;
165 }
166 
167 
VisitTryFinallyStatement(TryFinallyStatement * stmt)168 void BreakableStatementChecker::VisitTryFinallyStatement(
169     TryFinallyStatement* stmt) {
170   // Mark try finally as breakable to avoid adding a break slot in front of it.
171   is_breakable_ = true;
172 }
173 
174 
VisitDebuggerStatement(DebuggerStatement * stmt)175 void BreakableStatementChecker::VisitDebuggerStatement(
176     DebuggerStatement* stmt) {
177   // The debugger statement is breakable.
178   is_breakable_ = true;
179 }
180 
181 
VisitFunctionLiteral(FunctionLiteral * expr)182 void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
183 }
184 
185 
VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral * expr)186 void BreakableStatementChecker::VisitSharedFunctionInfoLiteral(
187     SharedFunctionInfoLiteral* expr) {
188 }
189 
190 
VisitConditional(Conditional * expr)191 void BreakableStatementChecker::VisitConditional(Conditional* expr) {
192 }
193 
194 
VisitVariableProxy(VariableProxy * expr)195 void BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) {
196 }
197 
198 
VisitLiteral(Literal * expr)199 void BreakableStatementChecker::VisitLiteral(Literal* expr) {
200 }
201 
202 
VisitRegExpLiteral(RegExpLiteral * expr)203 void BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
204 }
205 
206 
VisitObjectLiteral(ObjectLiteral * expr)207 void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) {
208 }
209 
210 
VisitArrayLiteral(ArrayLiteral * expr)211 void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
212 }
213 
214 
VisitAssignment(Assignment * expr)215 void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
216   // If assigning to a property (including a global property) the assignment is
217   // breakable.
218   VariableProxy* proxy = expr->target()->AsVariableProxy();
219   Property* prop = expr->target()->AsProperty();
220   if (prop != NULL || (proxy != NULL && proxy->var()->IsUnallocated())) {
221     is_breakable_ = true;
222     return;
223   }
224 
225   // Otherwise the assignment is breakable if the assigned value is.
226   Visit(expr->value());
227 }
228 
229 
VisitThrow(Throw * expr)230 void BreakableStatementChecker::VisitThrow(Throw* expr) {
231   // Throw is breakable if the expression is.
232   Visit(expr->exception());
233 }
234 
235 
VisitProperty(Property * expr)236 void BreakableStatementChecker::VisitProperty(Property* expr) {
237   // Property load is breakable.
238   is_breakable_ = true;
239 }
240 
241 
VisitCall(Call * expr)242 void BreakableStatementChecker::VisitCall(Call* expr) {
243   // Function calls both through IC and call stub are breakable.
244   is_breakable_ = true;
245 }
246 
247 
VisitCallNew(CallNew * expr)248 void BreakableStatementChecker::VisitCallNew(CallNew* expr) {
249   // Function calls through new are breakable.
250   is_breakable_ = true;
251 }
252 
253 
VisitCallRuntime(CallRuntime * expr)254 void BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) {
255 }
256 
257 
VisitUnaryOperation(UnaryOperation * expr)258 void BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) {
259   Visit(expr->expression());
260 }
261 
262 
VisitCountOperation(CountOperation * expr)263 void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
264   Visit(expr->expression());
265 }
266 
267 
VisitBinaryOperation(BinaryOperation * expr)268 void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
269   Visit(expr->left());
270   if (expr->op() != Token::AND &&
271       expr->op() != Token::OR) {
272     Visit(expr->right());
273   }
274 }
275 
276 
VisitCompareOperation(CompareOperation * expr)277 void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
278   Visit(expr->left());
279   Visit(expr->right());
280 }
281 
282 
VisitThisFunction(ThisFunction * expr)283 void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
284 }
285 
286 
287 #define __ ACCESS_MASM(masm())
288 
MakeCode(CompilationInfo * info)289 bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
290   Isolate* isolate = info->isolate();
291   Handle<Script> script = info->script();
292   if (!script->IsUndefined() && !script->source()->IsUndefined()) {
293     int len = String::cast(script->source())->length();
294     isolate->counters()->total_full_codegen_source_size()->Increment(len);
295   }
296   if (FLAG_trace_codegen) {
297     PrintF("Full Compiler - ");
298   }
299   CodeGenerator::MakeCodePrologue(info);
300   const int kInitialBufferSize = 4 * KB;
301   MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize);
302 #ifdef ENABLE_GDB_JIT_INTERFACE
303   masm.positions_recorder()->StartGDBJITLineInfoRecording();
304 #endif
305 
306   FullCodeGenerator cgen(&masm, info);
307   cgen.Generate();
308   if (cgen.HasStackOverflow()) {
309     ASSERT(!isolate->has_pending_exception());
310     return false;
311   }
312   unsigned table_offset = cgen.EmitStackCheckTable();
313 
314   Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
315   Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
316   code->set_optimizable(info->IsOptimizable() &&
317                         !info->function()->flags()->Contains(kDontOptimize) &&
318                         info->function()->scope()->AllowsLazyRecompilation());
319   code->set_self_optimization_header(cgen.has_self_optimization_header_);
320   cgen.PopulateDeoptimizationData(code);
321   cgen.PopulateTypeFeedbackInfo(code);
322   cgen.PopulateTypeFeedbackCells(code);
323   code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
324   code->set_handler_table(*cgen.handler_table());
325 #ifdef ENABLE_DEBUGGER_SUPPORT
326   code->set_has_debug_break_slots(
327       info->isolate()->debugger()->IsDebuggerActive());
328   code->set_compiled_optimizable(info->IsOptimizable());
329 #endif  // ENABLE_DEBUGGER_SUPPORT
330   code->set_allow_osr_at_loop_nesting_level(0);
331   code->set_profiler_ticks(0);
332   code->set_stack_check_table_offset(table_offset);
333   CodeGenerator::PrintCode(code, info);
334   info->SetCode(code);  // May be an empty handle.
335   if (!code.is_null()) {
336     isolate->runtime_profiler()->NotifyCodeGenerated(code->instruction_size());
337   }
338 #ifdef ENABLE_GDB_JIT_INTERFACE
339   if (FLAG_gdbjit && !code.is_null()) {
340     GDBJITLineInfo* lineinfo =
341         masm.positions_recorder()->DetachGDBJITLineInfo();
342 
343     GDBJIT(RegisterDetailedLineInfo(*code, lineinfo));
344   }
345 #endif
346   return !code.is_null();
347 }
348 
349 
EmitStackCheckTable()350 unsigned FullCodeGenerator::EmitStackCheckTable() {
351   // The stack check table consists of a length (in number of entries)
352   // field, and then a sequence of entries.  Each entry is a pair of AST id
353   // and code-relative pc offset.
354   masm()->Align(kIntSize);
355   unsigned offset = masm()->pc_offset();
356   unsigned length = stack_checks_.length();
357   __ dd(length);
358   for (unsigned i = 0; i < length; ++i) {
359     __ dd(stack_checks_[i].id);
360     __ dd(stack_checks_[i].pc_and_state);
361   }
362   return offset;
363 }
364 
365 
PopulateDeoptimizationData(Handle<Code> code)366 void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
367   // Fill in the deoptimization information.
368   ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
369   if (!info_->HasDeoptimizationSupport()) return;
370   int length = bailout_entries_.length();
371   Handle<DeoptimizationOutputData> data = isolate()->factory()->
372       NewDeoptimizationOutputData(length, TENURED);
373   for (int i = 0; i < length; i++) {
374     data->SetAstId(i, Smi::FromInt(bailout_entries_[i].id));
375     data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
376   }
377   code->set_deoptimization_data(*data);
378 }
379 
380 
PopulateTypeFeedbackInfo(Handle<Code> code)381 void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
382   Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo();
383   info->set_ic_total_count(ic_total_count_);
384   ASSERT(!isolate()->heap()->InNewSpace(*info));
385   code->set_type_feedback_info(*info);
386 }
387 
388 
PopulateTypeFeedbackCells(Handle<Code> code)389 void FullCodeGenerator::PopulateTypeFeedbackCells(Handle<Code> code) {
390   if (type_feedback_cells_.is_empty()) return;
391   int length = type_feedback_cells_.length();
392   int array_size = TypeFeedbackCells::LengthOfFixedArray(length);
393   Handle<TypeFeedbackCells> cache = Handle<TypeFeedbackCells>::cast(
394       isolate()->factory()->NewFixedArray(array_size, TENURED));
395   for (int i = 0; i < length; i++) {
396     cache->SetAstId(i, Smi::FromInt(type_feedback_cells_[i].ast_id));
397     cache->SetCell(i, *type_feedback_cells_[i].cell);
398   }
399   TypeFeedbackInfo::cast(code->type_feedback_info())->set_type_feedback_cells(
400       *cache);
401 }
402 
403 
404 
PrepareForBailout(Expression * node,State state)405 void FullCodeGenerator::PrepareForBailout(Expression* node, State state) {
406   PrepareForBailoutForId(node->id(), state);
407 }
408 
409 
RecordJSReturnSite(Call * call)410 void FullCodeGenerator::RecordJSReturnSite(Call* call) {
411   // We record the offset of the function return so we can rebuild the frame
412   // if the function was inlined, i.e., this is the return address in the
413   // inlined function's frame.
414   //
415   // The state is ignored.  We defensively set it to TOS_REG, which is the
416   // real state of the unoptimized code at the return site.
417   PrepareForBailoutForId(call->ReturnId(), TOS_REG);
418 #ifdef DEBUG
419   // In debug builds, mark the return so we can verify that this function
420   // was called.
421   ASSERT(!call->return_is_recorded_);
422   call->return_is_recorded_ = true;
423 #endif
424 }
425 
426 
PrepareForBailoutForId(unsigned id,State state)427 void FullCodeGenerator::PrepareForBailoutForId(unsigned id, State state) {
428   // There's no need to prepare this code for bailouts from already optimized
429   // code or code that can't be optimized.
430   if (!info_->HasDeoptimizationSupport()) return;
431   unsigned pc_and_state =
432       StateField::encode(state) | PcField::encode(masm_->pc_offset());
433   ASSERT(Smi::IsValid(pc_and_state));
434   BailoutEntry entry = { id, pc_and_state };
435 #ifdef DEBUG
436   if (FLAG_enable_slow_asserts) {
437     // Assert that we don't have multiple bailout entries for the same node.
438     for (int i = 0; i < bailout_entries_.length(); i++) {
439       if (bailout_entries_.at(i).id == entry.id) {
440         AstPrinter printer;
441         PrintF("%s", printer.PrintProgram(info_->function()));
442         UNREACHABLE();
443       }
444     }
445   }
446 #endif  // DEBUG
447   bailout_entries_.Add(entry);
448 }
449 
450 
RecordTypeFeedbackCell(unsigned id,Handle<JSGlobalPropertyCell> cell)451 void FullCodeGenerator::RecordTypeFeedbackCell(
452     unsigned id, Handle<JSGlobalPropertyCell> cell) {
453   TypeFeedbackCellEntry entry = { id, cell };
454   type_feedback_cells_.Add(entry);
455 }
456 
457 
RecordStackCheck(unsigned ast_id)458 void FullCodeGenerator::RecordStackCheck(unsigned ast_id) {
459   // The pc offset does not need to be encoded and packed together with a
460   // state.
461   ASSERT(masm_->pc_offset() > 0);
462   BailoutEntry entry = { ast_id, static_cast<unsigned>(masm_->pc_offset()) };
463   stack_checks_.Add(entry);
464 }
465 
466 
ShouldInlineSmiCase(Token::Value op)467 bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
468   // Inline smi case inside loops, but not division and modulo which
469   // are too complicated and take up too much space.
470   if (op == Token::DIV ||op == Token::MOD) return false;
471   if (FLAG_always_inline_smi_code) return true;
472   return loop_depth_ > 0;
473 }
474 
475 
Plug(Register reg) const476 void FullCodeGenerator::EffectContext::Plug(Register reg) const {
477 }
478 
479 
Plug(Register reg) const480 void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
481   __ Move(result_register(), reg);
482 }
483 
484 
Plug(Register reg) const485 void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
486   __ push(reg);
487 }
488 
489 
Plug(Register reg) const490 void FullCodeGenerator::TestContext::Plug(Register reg) const {
491   // For simplicity we always test the accumulator register.
492   __ Move(result_register(), reg);
493   codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
494   codegen()->DoTest(this);
495 }
496 
497 
PlugTOS() const498 void FullCodeGenerator::EffectContext::PlugTOS() const {
499   __ Drop(1);
500 }
501 
502 
PlugTOS() const503 void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
504   __ pop(result_register());
505 }
506 
507 
PlugTOS() const508 void FullCodeGenerator::StackValueContext::PlugTOS() const {
509 }
510 
511 
PlugTOS() const512 void FullCodeGenerator::TestContext::PlugTOS() const {
513   // For simplicity we always test the accumulator register.
514   __ pop(result_register());
515   codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
516   codegen()->DoTest(this);
517 }
518 
519 
PrepareTest(Label * materialize_true,Label * materialize_false,Label ** if_true,Label ** if_false,Label ** fall_through) const520 void FullCodeGenerator::EffectContext::PrepareTest(
521     Label* materialize_true,
522     Label* materialize_false,
523     Label** if_true,
524     Label** if_false,
525     Label** fall_through) const {
526   // In an effect context, the true and the false case branch to the
527   // same label.
528   *if_true = *if_false = *fall_through = materialize_true;
529 }
530 
531 
PrepareTest(Label * materialize_true,Label * materialize_false,Label ** if_true,Label ** if_false,Label ** fall_through) const532 void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
533     Label* materialize_true,
534     Label* materialize_false,
535     Label** if_true,
536     Label** if_false,
537     Label** fall_through) const {
538   *if_true = *fall_through = materialize_true;
539   *if_false = materialize_false;
540 }
541 
542 
PrepareTest(Label * materialize_true,Label * materialize_false,Label ** if_true,Label ** if_false,Label ** fall_through) const543 void FullCodeGenerator::StackValueContext::PrepareTest(
544     Label* materialize_true,
545     Label* materialize_false,
546     Label** if_true,
547     Label** if_false,
548     Label** fall_through) const {
549   *if_true = *fall_through = materialize_true;
550   *if_false = materialize_false;
551 }
552 
553 
PrepareTest(Label * materialize_true,Label * materialize_false,Label ** if_true,Label ** if_false,Label ** fall_through) const554 void FullCodeGenerator::TestContext::PrepareTest(
555     Label* materialize_true,
556     Label* materialize_false,
557     Label** if_true,
558     Label** if_false,
559     Label** fall_through) const {
560   *if_true = true_label_;
561   *if_false = false_label_;
562   *fall_through = fall_through_;
563 }
564 
565 
DoTest(const TestContext * context)566 void FullCodeGenerator::DoTest(const TestContext* context) {
567   DoTest(context->condition(),
568          context->true_label(),
569          context->false_label(),
570          context->fall_through());
571 }
572 
573 
VisitDeclarations(ZoneList<Declaration * > * declarations)574 void FullCodeGenerator::VisitDeclarations(
575     ZoneList<Declaration*>* declarations) {
576   int save_global_count = global_count_;
577   global_count_ = 0;
578 
579   AstVisitor::VisitDeclarations(declarations);
580 
581   // Batch declare global functions and variables.
582   if (global_count_ > 0) {
583     Handle<FixedArray> array =
584        isolate()->factory()->NewFixedArray(2 * global_count_, TENURED);
585     int length = declarations->length();
586     for (int j = 0, i = 0; i < length; i++) {
587       Declaration* decl = declarations->at(i);
588       Variable* var = decl->proxy()->var();
589 
590       if (var->IsUnallocated()) {
591         array->set(j++, *(var->name()));
592         FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
593         if (fun_decl == NULL) {
594           if (var->binding_needs_init()) {
595             // In case this binding needs initialization use the hole.
596             array->set_the_hole(j++);
597           } else {
598             array->set_undefined(j++);
599           }
600         } else {
601           Handle<SharedFunctionInfo> function =
602               Compiler::BuildFunctionInfo(fun_decl->fun(), script());
603           // Check for stack-overflow exception.
604           if (function.is_null()) {
605             SetStackOverflow();
606             return;
607           }
608           array->set(j++, *function);
609         }
610       }
611     }
612     // Invoke the platform-dependent code generator to do the actual
613     // declaration the global functions and variables.
614     DeclareGlobals(array);
615   }
616 
617   global_count_ = save_global_count;
618 }
619 
620 
VisitVariableDeclaration(VariableDeclaration * decl)621 void FullCodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
622   EmitDeclaration(decl->proxy(), decl->mode(), NULL);
623 }
624 
625 
VisitFunctionDeclaration(FunctionDeclaration * decl)626 void FullCodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
627   EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
628 }
629 
630 
VisitModuleDeclaration(ModuleDeclaration * decl)631 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* decl) {
632   EmitDeclaration(decl->proxy(), decl->mode(), NULL);
633 }
634 
635 
VisitImportDeclaration(ImportDeclaration * decl)636 void FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) {
637   EmitDeclaration(decl->proxy(), decl->mode(), NULL);
638 }
639 
640 
VisitExportDeclaration(ExportDeclaration * decl)641 void FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) {
642   // TODO(rossberg)
643 }
644 
645 
VisitModuleLiteral(ModuleLiteral * module)646 void FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) {
647   // TODO(rossberg)
648 }
649 
650 
VisitModuleVariable(ModuleVariable * module)651 void FullCodeGenerator::VisitModuleVariable(ModuleVariable* module) {
652   // TODO(rossberg)
653 }
654 
655 
VisitModulePath(ModulePath * module)656 void FullCodeGenerator::VisitModulePath(ModulePath* module) {
657   // TODO(rossberg)
658 }
659 
660 
VisitModuleUrl(ModuleUrl * decl)661 void FullCodeGenerator::VisitModuleUrl(ModuleUrl* decl) {
662   // TODO(rossberg)
663 }
664 
665 
DeclareGlobalsFlags()666 int FullCodeGenerator::DeclareGlobalsFlags() {
667   ASSERT(DeclareGlobalsLanguageMode::is_valid(language_mode()));
668   return DeclareGlobalsEvalFlag::encode(is_eval()) |
669       DeclareGlobalsNativeFlag::encode(is_native()) |
670       DeclareGlobalsLanguageMode::encode(language_mode());
671 }
672 
673 
SetFunctionPosition(FunctionLiteral * fun)674 void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
675   CodeGenerator::RecordPositions(masm_, fun->start_position());
676 }
677 
678 
SetReturnPosition(FunctionLiteral * fun)679 void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
680   CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
681 }
682 
683 
SetStatementPosition(Statement * stmt)684 void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
685 #ifdef ENABLE_DEBUGGER_SUPPORT
686   if (!isolate()->debugger()->IsDebuggerActive()) {
687     CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
688   } else {
689     // Check if the statement will be breakable without adding a debug break
690     // slot.
691     BreakableStatementChecker checker;
692     checker.Check(stmt);
693     // Record the statement position right here if the statement is not
694     // breakable. For breakable statements the actual recording of the
695     // position will be postponed to the breakable code (typically an IC).
696     bool position_recorded = CodeGenerator::RecordPositions(
697         masm_, stmt->statement_pos(), !checker.is_breakable());
698     // If the position recording did record a new position generate a debug
699     // break slot to make the statement breakable.
700     if (position_recorded) {
701       Debug::GenerateSlot(masm_);
702     }
703   }
704 #else
705   CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
706 #endif
707 }
708 
709 
SetExpressionPosition(Expression * expr,int pos)710 void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) {
711 #ifdef ENABLE_DEBUGGER_SUPPORT
712   if (!isolate()->debugger()->IsDebuggerActive()) {
713     CodeGenerator::RecordPositions(masm_, pos);
714   } else {
715     // Check if the expression will be breakable without adding a debug break
716     // slot.
717     BreakableStatementChecker checker;
718     checker.Check(expr);
719     // Record a statement position right here if the expression is not
720     // breakable. For breakable expressions the actual recording of the
721     // position will be postponed to the breakable code (typically an IC).
722     // NOTE this will record a statement position for something which might
723     // not be a statement. As stepping in the debugger will only stop at
724     // statement positions this is used for e.g. the condition expression of
725     // a do while loop.
726     bool position_recorded = CodeGenerator::RecordPositions(
727         masm_, pos, !checker.is_breakable());
728     // If the position recording did record a new position generate a debug
729     // break slot to make the statement breakable.
730     if (position_recorded) {
731       Debug::GenerateSlot(masm_);
732     }
733   }
734 #else
735   CodeGenerator::RecordPositions(masm_, pos);
736 #endif
737 }
738 
739 
SetStatementPosition(int pos)740 void FullCodeGenerator::SetStatementPosition(int pos) {
741   CodeGenerator::RecordPositions(masm_, pos);
742 }
743 
744 
SetSourcePosition(int pos)745 void FullCodeGenerator::SetSourcePosition(int pos) {
746   if (pos != RelocInfo::kNoPosition) {
747     masm_->positions_recorder()->RecordPosition(pos);
748   }
749 }
750 
751 
752 // Lookup table for code generators for  special runtime calls which are
753 // generated inline.
754 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)          \
755     &FullCodeGenerator::Emit##Name,
756 
757 const FullCodeGenerator::InlineFunctionGenerator
758   FullCodeGenerator::kInlineFunctionGenerators[] = {
759     INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
760     INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
761   };
762 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
763 
764 
765 FullCodeGenerator::InlineFunctionGenerator
FindInlineFunctionGenerator(Runtime::FunctionId id)766   FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
767     int lookup_index =
768         static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction);
769     ASSERT(lookup_index >= 0);
770     ASSERT(static_cast<size_t>(lookup_index) <
771            ARRAY_SIZE(kInlineFunctionGenerators));
772     return kInlineFunctionGenerators[lookup_index];
773 }
774 
775 
EmitInlineRuntimeCall(CallRuntime * expr)776 void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
777   const Runtime::Function* function = expr->function();
778   ASSERT(function != NULL);
779   ASSERT(function->intrinsic_type == Runtime::INLINE);
780   InlineFunctionGenerator generator =
781       FindInlineFunctionGenerator(function->function_id);
782   ((*this).*(generator))(expr);
783 }
784 
785 
VisitBinaryOperation(BinaryOperation * expr)786 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
787   switch (expr->op()) {
788     case Token::COMMA:
789       return VisitComma(expr);
790     case Token::OR:
791     case Token::AND:
792       return VisitLogicalExpression(expr);
793     default:
794       return VisitArithmeticExpression(expr);
795   }
796 }
797 
798 
VisitInDuplicateContext(Expression * expr)799 void FullCodeGenerator::VisitInDuplicateContext(Expression* expr) {
800   if (context()->IsEffect()) {
801     VisitForEffect(expr);
802   } else if (context()->IsAccumulatorValue()) {
803     VisitForAccumulatorValue(expr);
804   } else if (context()->IsStackValue()) {
805     VisitForStackValue(expr);
806   } else if (context()->IsTest()) {
807     const TestContext* test = TestContext::cast(context());
808     VisitForControl(expr, test->true_label(), test->false_label(),
809                     test->fall_through());
810   }
811 }
812 
813 
VisitComma(BinaryOperation * expr)814 void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
815   Comment cmnt(masm_, "[ Comma");
816   VisitForEffect(expr->left());
817   VisitInDuplicateContext(expr->right());
818 }
819 
820 
VisitLogicalExpression(BinaryOperation * expr)821 void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
822   bool is_logical_and = expr->op() == Token::AND;
823   Comment cmnt(masm_, is_logical_and ? "[ Logical AND" :  "[ Logical OR");
824   Expression* left = expr->left();
825   Expression* right = expr->right();
826   int right_id = expr->RightId();
827   Label done;
828 
829   if (context()->IsTest()) {
830     Label eval_right;
831     const TestContext* test = TestContext::cast(context());
832     if (is_logical_and) {
833       VisitForControl(left, &eval_right, test->false_label(), &eval_right);
834     } else {
835       VisitForControl(left, test->true_label(), &eval_right, &eval_right);
836     }
837     PrepareForBailoutForId(right_id, NO_REGISTERS);
838     __ bind(&eval_right);
839 
840   } else if (context()->IsAccumulatorValue()) {
841     VisitForAccumulatorValue(left);
842     // We want the value in the accumulator for the test, and on the stack in
843     // case we need it.
844     __ push(result_register());
845     Label discard, restore;
846     if (is_logical_and) {
847       DoTest(left, &discard, &restore, &restore);
848     } else {
849       DoTest(left, &restore, &discard, &restore);
850     }
851     __ bind(&restore);
852     __ pop(result_register());
853     __ jmp(&done);
854     __ bind(&discard);
855     __ Drop(1);
856     PrepareForBailoutForId(right_id, NO_REGISTERS);
857 
858   } else if (context()->IsStackValue()) {
859     VisitForAccumulatorValue(left);
860     // We want the value in the accumulator for the test, and on the stack in
861     // case we need it.
862     __ push(result_register());
863     Label discard;
864     if (is_logical_and) {
865       DoTest(left, &discard, &done, &discard);
866     } else {
867       DoTest(left, &done, &discard, &discard);
868     }
869     __ bind(&discard);
870     __ Drop(1);
871     PrepareForBailoutForId(right_id, NO_REGISTERS);
872 
873   } else {
874     ASSERT(context()->IsEffect());
875     Label eval_right;
876     if (is_logical_and) {
877       VisitForControl(left, &eval_right, &done, &eval_right);
878     } else {
879       VisitForControl(left, &done, &eval_right, &eval_right);
880     }
881     PrepareForBailoutForId(right_id, NO_REGISTERS);
882     __ bind(&eval_right);
883   }
884 
885   VisitInDuplicateContext(right);
886   __ bind(&done);
887 }
888 
889 
VisitArithmeticExpression(BinaryOperation * expr)890 void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
891   Token::Value op = expr->op();
892   Comment cmnt(masm_, "[ ArithmeticExpression");
893   Expression* left = expr->left();
894   Expression* right = expr->right();
895   OverwriteMode mode =
896       left->ResultOverwriteAllowed()
897       ? OVERWRITE_LEFT
898       : (right->ResultOverwriteAllowed() ? OVERWRITE_RIGHT : NO_OVERWRITE);
899 
900   VisitForStackValue(left);
901   VisitForAccumulatorValue(right);
902 
903   SetSourcePosition(expr->position());
904   if (ShouldInlineSmiCase(op)) {
905     EmitInlineSmiBinaryOp(expr, op, mode, left, right);
906   } else {
907     EmitBinaryOp(expr, op, mode);
908   }
909 }
910 
911 
VisitBlock(Block * stmt)912 void FullCodeGenerator::VisitBlock(Block* stmt) {
913   Comment cmnt(masm_, "[ Block");
914   NestedBlock nested_block(this, stmt);
915   SetStatementPosition(stmt);
916 
917   Scope* saved_scope = scope();
918   // Push a block context when entering a block with block scoped variables.
919   if (stmt->block_scope() != NULL) {
920     { Comment cmnt(masm_, "[ Extend block context");
921       scope_ = stmt->block_scope();
922       Handle<ScopeInfo> scope_info = scope_->GetScopeInfo();
923       int heap_slots = scope_info->ContextLength() - Context::MIN_CONTEXT_SLOTS;
924       __ Push(scope_info);
925       PushFunctionArgumentForContextAllocation();
926       if (heap_slots <= FastNewBlockContextStub::kMaximumSlots) {
927         FastNewBlockContextStub stub(heap_slots);
928         __ CallStub(&stub);
929       } else {
930         __ CallRuntime(Runtime::kPushBlockContext, 2);
931       }
932 
933       // Replace the context stored in the frame.
934       StoreToFrameField(StandardFrameConstants::kContextOffset,
935                         context_register());
936     }
937     { Comment cmnt(masm_, "[ Declarations");
938       VisitDeclarations(scope_->declarations());
939     }
940   }
941   PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
942   VisitStatements(stmt->statements());
943   scope_ = saved_scope;
944   __ bind(nested_block.break_label());
945   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
946 
947   // Pop block context if necessary.
948   if (stmt->block_scope() != NULL) {
949     LoadContextField(context_register(), Context::PREVIOUS_INDEX);
950     // Update local stack frame context field.
951     StoreToFrameField(StandardFrameConstants::kContextOffset,
952                       context_register());
953   }
954 }
955 
956 
VisitExpressionStatement(ExpressionStatement * stmt)957 void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
958   Comment cmnt(masm_, "[ ExpressionStatement");
959   SetStatementPosition(stmt);
960   VisitForEffect(stmt->expression());
961 }
962 
963 
VisitEmptyStatement(EmptyStatement * stmt)964 void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
965   Comment cmnt(masm_, "[ EmptyStatement");
966   SetStatementPosition(stmt);
967 }
968 
969 
VisitIfStatement(IfStatement * stmt)970 void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
971   Comment cmnt(masm_, "[ IfStatement");
972   SetStatementPosition(stmt);
973   Label then_part, else_part, done;
974 
975   if (stmt->HasElseStatement()) {
976     VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
977     PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
978     __ bind(&then_part);
979     Visit(stmt->then_statement());
980     __ jmp(&done);
981 
982     PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
983     __ bind(&else_part);
984     Visit(stmt->else_statement());
985   } else {
986     VisitForControl(stmt->condition(), &then_part, &done, &then_part);
987     PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
988     __ bind(&then_part);
989     Visit(stmt->then_statement());
990 
991     PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
992   }
993   __ bind(&done);
994   PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
995 }
996 
997 
VisitContinueStatement(ContinueStatement * stmt)998 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
999   Comment cmnt(masm_,  "[ ContinueStatement");
1000   SetStatementPosition(stmt);
1001   NestedStatement* current = nesting_stack_;
1002   int stack_depth = 0;
1003   int context_length = 0;
1004   // When continuing, we clobber the unpredictable value in the accumulator
1005   // with one that's safe for GC.  If we hit an exit from the try block of
1006   // try...finally on our way out, we will unconditionally preserve the
1007   // accumulator on the stack.
1008   ClearAccumulator();
1009   while (!current->IsContinueTarget(stmt->target())) {
1010     current = current->Exit(&stack_depth, &context_length);
1011   }
1012   __ Drop(stack_depth);
1013   if (context_length > 0) {
1014     while (context_length > 0) {
1015       LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1016       --context_length;
1017     }
1018     StoreToFrameField(StandardFrameConstants::kContextOffset,
1019                       context_register());
1020   }
1021 
1022   __ jmp(current->AsIteration()->continue_label());
1023 }
1024 
1025 
VisitBreakStatement(BreakStatement * stmt)1026 void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
1027   Comment cmnt(masm_,  "[ BreakStatement");
1028   SetStatementPosition(stmt);
1029   NestedStatement* current = nesting_stack_;
1030   int stack_depth = 0;
1031   int context_length = 0;
1032   // When breaking, we clobber the unpredictable value in the accumulator
1033   // with one that's safe for GC.  If we hit an exit from the try block of
1034   // try...finally on our way out, we will unconditionally preserve the
1035   // accumulator on the stack.
1036   ClearAccumulator();
1037   while (!current->IsBreakTarget(stmt->target())) {
1038     current = current->Exit(&stack_depth, &context_length);
1039   }
1040   __ Drop(stack_depth);
1041   if (context_length > 0) {
1042     while (context_length > 0) {
1043       LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1044       --context_length;
1045     }
1046     StoreToFrameField(StandardFrameConstants::kContextOffset,
1047                       context_register());
1048   }
1049 
1050   __ jmp(current->AsBreakable()->break_label());
1051 }
1052 
1053 
VisitReturnStatement(ReturnStatement * stmt)1054 void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
1055   Comment cmnt(masm_, "[ ReturnStatement");
1056   SetStatementPosition(stmt);
1057   Expression* expr = stmt->expression();
1058   VisitForAccumulatorValue(expr);
1059 
1060   // Exit all nested statements.
1061   NestedStatement* current = nesting_stack_;
1062   int stack_depth = 0;
1063   int context_length = 0;
1064   while (current != NULL) {
1065     current = current->Exit(&stack_depth, &context_length);
1066   }
1067   __ Drop(stack_depth);
1068 
1069   EmitReturnSequence();
1070 }
1071 
1072 
VisitWithStatement(WithStatement * stmt)1073 void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
1074   Comment cmnt(masm_, "[ WithStatement");
1075   SetStatementPosition(stmt);
1076 
1077   VisitForStackValue(stmt->expression());
1078   PushFunctionArgumentForContextAllocation();
1079   __ CallRuntime(Runtime::kPushWithContext, 2);
1080   StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1081 
1082   { WithOrCatch body(this);
1083     Visit(stmt->statement());
1084   }
1085 
1086   // Pop context.
1087   LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1088   // Update local stack frame context field.
1089   StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1090 }
1091 
1092 
VisitDoWhileStatement(DoWhileStatement * stmt)1093 void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
1094   Comment cmnt(masm_, "[ DoWhileStatement");
1095   SetStatementPosition(stmt);
1096   Label body, stack_check;
1097 
1098   Iteration loop_statement(this, stmt);
1099   increment_loop_depth();
1100 
1101   __ bind(&body);
1102   Visit(stmt->body());
1103 
1104   // Record the position of the do while condition and make sure it is
1105   // possible to break on the condition.
1106   __ bind(loop_statement.continue_label());
1107   PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
1108   SetExpressionPosition(stmt->cond(), stmt->condition_position());
1109   VisitForControl(stmt->cond(),
1110                   &stack_check,
1111                   loop_statement.break_label(),
1112                   &stack_check);
1113 
1114   // Check stack before looping.
1115   PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
1116   __ bind(&stack_check);
1117   EmitStackCheck(stmt, &body);
1118   __ jmp(&body);
1119 
1120   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1121   __ bind(loop_statement.break_label());
1122   decrement_loop_depth();
1123 }
1124 
1125 
VisitWhileStatement(WhileStatement * stmt)1126 void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1127   Comment cmnt(masm_, "[ WhileStatement");
1128   Label test, body;
1129 
1130   Iteration loop_statement(this, stmt);
1131   increment_loop_depth();
1132 
1133   // Emit the test at the bottom of the loop.
1134   __ jmp(&test);
1135 
1136   PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1137   __ bind(&body);
1138   Visit(stmt->body());
1139 
1140   // Emit the statement position here as this is where the while
1141   // statement code starts.
1142   __ bind(loop_statement.continue_label());
1143   SetStatementPosition(stmt);
1144 
1145   // Check stack before looping.
1146   EmitStackCheck(stmt, &body);
1147 
1148   __ bind(&test);
1149   VisitForControl(stmt->cond(),
1150                   &body,
1151                   loop_statement.break_label(),
1152                   loop_statement.break_label());
1153 
1154   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1155   __ bind(loop_statement.break_label());
1156   decrement_loop_depth();
1157 }
1158 
1159 
VisitForStatement(ForStatement * stmt)1160 void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
1161   Comment cmnt(masm_, "[ ForStatement");
1162   Label test, body;
1163 
1164   Iteration loop_statement(this, stmt);
1165 
1166   // Set statement position for a break slot before entering the for-body.
1167   SetStatementPosition(stmt);
1168 
1169   if (stmt->init() != NULL) {
1170     Visit(stmt->init());
1171   }
1172 
1173   increment_loop_depth();
1174   // Emit the test at the bottom of the loop (even if empty).
1175   __ jmp(&test);
1176 
1177   PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1178   __ bind(&body);
1179   Visit(stmt->body());
1180 
1181   PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
1182   __ bind(loop_statement.continue_label());
1183   if (stmt->next() != NULL) {
1184     Visit(stmt->next());
1185   }
1186 
1187   // Emit the statement position here as this is where the for
1188   // statement code starts.
1189   SetStatementPosition(stmt);
1190 
1191   // Check stack before looping.
1192   EmitStackCheck(stmt, &body);
1193 
1194   __ bind(&test);
1195   if (stmt->cond() != NULL) {
1196     VisitForControl(stmt->cond(),
1197                     &body,
1198                     loop_statement.break_label(),
1199                     loop_statement.break_label());
1200   } else {
1201     __ jmp(&body);
1202   }
1203 
1204   PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1205   __ bind(loop_statement.break_label());
1206   decrement_loop_depth();
1207 }
1208 
1209 
VisitTryCatchStatement(TryCatchStatement * stmt)1210 void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1211   Comment cmnt(masm_, "[ TryCatchStatement");
1212   SetStatementPosition(stmt);
1213   // The try block adds a handler to the exception handler chain before
1214   // entering, and removes it again when exiting normally.  If an exception
1215   // is thrown during execution of the try block, the handler is consumed
1216   // and control is passed to the catch block with the exception in the
1217   // result register.
1218 
1219   Label try_entry, handler_entry, exit;
1220   __ jmp(&try_entry);
1221   __ bind(&handler_entry);
1222   handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
1223   // Exception handler code, the exception is in the result register.
1224   // Extend the context before executing the catch block.
1225   { Comment cmnt(masm_, "[ Extend catch context");
1226     __ Push(stmt->variable()->name());
1227     __ push(result_register());
1228     PushFunctionArgumentForContextAllocation();
1229     __ CallRuntime(Runtime::kPushCatchContext, 3);
1230     StoreToFrameField(StandardFrameConstants::kContextOffset,
1231                       context_register());
1232   }
1233 
1234   Scope* saved_scope = scope();
1235   scope_ = stmt->scope();
1236   ASSERT(scope_->declarations()->is_empty());
1237   { WithOrCatch catch_body(this);
1238     Visit(stmt->catch_block());
1239   }
1240   // Restore the context.
1241   LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1242   StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1243   scope_ = saved_scope;
1244   __ jmp(&exit);
1245 
1246   // Try block code. Sets up the exception handler chain.
1247   __ bind(&try_entry);
1248   __ PushTryHandler(StackHandler::CATCH, stmt->index());
1249   { TryCatch try_body(this);
1250     Visit(stmt->try_block());
1251   }
1252   __ PopTryHandler();
1253   __ bind(&exit);
1254 }
1255 
1256 
VisitTryFinallyStatement(TryFinallyStatement * stmt)1257 void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1258   Comment cmnt(masm_, "[ TryFinallyStatement");
1259   SetStatementPosition(stmt);
1260   // Try finally is compiled by setting up a try-handler on the stack while
1261   // executing the try body, and removing it again afterwards.
1262   //
1263   // The try-finally construct can enter the finally block in three ways:
1264   // 1. By exiting the try-block normally. This removes the try-handler and
1265   //    calls the finally block code before continuing.
1266   // 2. By exiting the try-block with a function-local control flow transfer
1267   //    (break/continue/return). The site of the, e.g., break removes the
1268   //    try handler and calls the finally block code before continuing
1269   //    its outward control transfer.
1270   // 3. By exiting the try-block with a thrown exception.
1271   //    This can happen in nested function calls. It traverses the try-handler
1272   //    chain and consumes the try-handler entry before jumping to the
1273   //    handler code. The handler code then calls the finally-block before
1274   //    rethrowing the exception.
1275   //
1276   // The finally block must assume a return address on top of the stack
1277   // (or in the link register on ARM chips) and a value (return value or
1278   // exception) in the result register (rax/eax/r0), both of which must
1279   // be preserved. The return address isn't GC-safe, so it should be
1280   // cooked before GC.
1281   Label try_entry, handler_entry, finally_entry;
1282 
1283   // Jump to try-handler setup and try-block code.
1284   __ jmp(&try_entry);
1285   __ bind(&handler_entry);
1286   handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
1287   // Exception handler code.  This code is only executed when an exception
1288   // is thrown.  The exception is in the result register, and must be
1289   // preserved by the finally block.  Call the finally block and then
1290   // rethrow the exception if it returns.
1291   __ Call(&finally_entry);
1292   __ push(result_register());
1293   __ CallRuntime(Runtime::kReThrow, 1);
1294 
1295   // Finally block implementation.
1296   __ bind(&finally_entry);
1297   EnterFinallyBlock();
1298   { Finally finally_body(this);
1299     Visit(stmt->finally_block());
1300   }
1301   ExitFinallyBlock();  // Return to the calling code.
1302 
1303   // Set up try handler.
1304   __ bind(&try_entry);
1305   __ PushTryHandler(StackHandler::FINALLY, stmt->index());
1306   { TryFinally try_body(this, &finally_entry);
1307     Visit(stmt->try_block());
1308   }
1309   __ PopTryHandler();
1310   // Execute the finally block on the way out.  Clobber the unpredictable
1311   // value in the result register with one that's safe for GC because the
1312   // finally block will unconditionally preserve the result register on the
1313   // stack.
1314   ClearAccumulator();
1315   __ Call(&finally_entry);
1316 }
1317 
1318 
VisitDebuggerStatement(DebuggerStatement * stmt)1319 void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1320 #ifdef ENABLE_DEBUGGER_SUPPORT
1321   Comment cmnt(masm_, "[ DebuggerStatement");
1322   SetStatementPosition(stmt);
1323 
1324   __ DebugBreak();
1325   // Ignore the return value.
1326 #endif
1327 }
1328 
1329 
VisitConditional(Conditional * expr)1330 void FullCodeGenerator::VisitConditional(Conditional* expr) {
1331   Comment cmnt(masm_, "[ Conditional");
1332   Label true_case, false_case, done;
1333   VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
1334 
1335   PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
1336   __ bind(&true_case);
1337   SetExpressionPosition(expr->then_expression(),
1338                         expr->then_expression_position());
1339   if (context()->IsTest()) {
1340     const TestContext* for_test = TestContext::cast(context());
1341     VisitForControl(expr->then_expression(),
1342                     for_test->true_label(),
1343                     for_test->false_label(),
1344                     NULL);
1345   } else {
1346     VisitInDuplicateContext(expr->then_expression());
1347     __ jmp(&done);
1348   }
1349 
1350   PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
1351   __ bind(&false_case);
1352   SetExpressionPosition(expr->else_expression(),
1353                         expr->else_expression_position());
1354   VisitInDuplicateContext(expr->else_expression());
1355   // If control flow falls through Visit, merge it with true case here.
1356   if (!context()->IsTest()) {
1357     __ bind(&done);
1358   }
1359 }
1360 
1361 
VisitLiteral(Literal * expr)1362 void FullCodeGenerator::VisitLiteral(Literal* expr) {
1363   Comment cmnt(masm_, "[ Literal");
1364   context()->Plug(expr->handle());
1365 }
1366 
1367 
VisitFunctionLiteral(FunctionLiteral * expr)1368 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1369   Comment cmnt(masm_, "[ FunctionLiteral");
1370 
1371   // Build the function boilerplate and instantiate it.
1372   Handle<SharedFunctionInfo> function_info =
1373       Compiler::BuildFunctionInfo(expr, script());
1374   if (function_info.is_null()) {
1375     SetStackOverflow();
1376     return;
1377   }
1378   EmitNewClosure(function_info, expr->pretenure());
1379 }
1380 
1381 
VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral * expr)1382 void FullCodeGenerator::VisitSharedFunctionInfoLiteral(
1383     SharedFunctionInfoLiteral* expr) {
1384   Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
1385   EmitNewClosure(expr->shared_function_info(), false);
1386 }
1387 
1388 
VisitThrow(Throw * expr)1389 void FullCodeGenerator::VisitThrow(Throw* expr) {
1390   Comment cmnt(masm_, "[ Throw");
1391   VisitForStackValue(expr->exception());
1392   __ CallRuntime(Runtime::kThrow, 1);
1393   // Never returns here.
1394 }
1395 
1396 
Exit(int * stack_depth,int * context_length)1397 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
1398     int* stack_depth,
1399     int* context_length) {
1400   // The macros used here must preserve the result register.
1401   __ Drop(*stack_depth);
1402   __ PopTryHandler();
1403   *stack_depth = 0;
1404   return previous_;
1405 }
1406 
1407 
TryLiteralCompare(CompareOperation * expr)1408 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
1409   Expression* sub_expr;
1410   Handle<String> check;
1411   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
1412     EmitLiteralCompareTypeof(expr, sub_expr, check);
1413     return true;
1414   }
1415 
1416   if (expr->IsLiteralCompareUndefined(&sub_expr)) {
1417     EmitLiteralCompareNil(expr, sub_expr, kUndefinedValue);
1418     return true;
1419   }
1420 
1421   if (expr->IsLiteralCompareNull(&sub_expr)) {
1422     EmitLiteralCompareNil(expr, sub_expr, kNullValue);
1423     return true;
1424   }
1425 
1426   return false;
1427 }
1428 
1429 
1430 #undef __
1431 
1432 
1433 } }  // namespace v8::internal
1434