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