The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / full-codegen.cc @ f230a1cf

History | View | Annotate | Download (54.9 KB)

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 "snapshot.h"
40
#include "stub-cache.h"
41

    
42
namespace v8 {
43
namespace internal {
44

    
45
void BreakableStatementChecker::Check(Statement* stmt) {
46
  Visit(stmt);
47
}
48

    
49

    
50
void BreakableStatementChecker::Check(Expression* expr) {
51
  Visit(expr);
52
}
53

    
54

    
55
void BreakableStatementChecker::VisitVariableDeclaration(
56
    VariableDeclaration* decl) {
57
}
58

    
59
void BreakableStatementChecker::VisitFunctionDeclaration(
60
    FunctionDeclaration* decl) {
61
}
62

    
63
void BreakableStatementChecker::VisitModuleDeclaration(
64
    ModuleDeclaration* decl) {
65
}
66

    
67
void BreakableStatementChecker::VisitImportDeclaration(
68
    ImportDeclaration* decl) {
69
}
70

    
71
void BreakableStatementChecker::VisitExportDeclaration(
72
    ExportDeclaration* decl) {
73
}
74

    
75

    
76
void BreakableStatementChecker::VisitModuleLiteral(ModuleLiteral* module) {
77
}
78

    
79

    
80
void BreakableStatementChecker::VisitModuleVariable(ModuleVariable* module) {
81
}
82

    
83

    
84
void BreakableStatementChecker::VisitModulePath(ModulePath* module) {
85
}
86

    
87

    
88
void BreakableStatementChecker::VisitModuleUrl(ModuleUrl* module) {
89
}
90

    
91

    
92
void BreakableStatementChecker::VisitModuleStatement(ModuleStatement* stmt) {
93
}
94

    
95

    
96
void BreakableStatementChecker::VisitBlock(Block* stmt) {
97
}
98

    
99

    
100
void BreakableStatementChecker::VisitExpressionStatement(
101
    ExpressionStatement* stmt) {
102
  // Check if expression is breakable.
103
  Visit(stmt->expression());
104
}
105

    
106

    
107
void BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) {
108
}
109

    
110

    
111
void BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) {
112
  // If the condition is breakable the if statement is breakable.
113
  Visit(stmt->condition());
114
}
115

    
116

    
117
void BreakableStatementChecker::VisitContinueStatement(
118
    ContinueStatement* stmt) {
119
}
120

    
121

    
122
void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
123
}
124

    
125

    
126
void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
127
  // Return is breakable if the expression is.
128
  Visit(stmt->expression());
129
}
130

    
131

    
132
void BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) {
133
  Visit(stmt->expression());
134
}
135

    
136

    
137
void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
138
  // Switch statements breakable if the tag expression is.
139
  Visit(stmt->tag());
140
}
141

    
142

    
143
void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
144
  // Mark do while as breakable to avoid adding a break slot in front of it.
145
  is_breakable_ = true;
146
}
147

    
148

    
149
void BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) {
150
  // Mark while statements breakable if the condition expression is.
151
  Visit(stmt->cond());
152
}
153

    
154

    
155
void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
156
  // Mark for statements breakable if the condition expression is.
157
  if (stmt->cond() != NULL) {
158
    Visit(stmt->cond());
159
  }
160
}
161

    
162

    
163
void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
164
  // Mark for in statements breakable if the enumerable expression is.
165
  Visit(stmt->enumerable());
166
}
167

    
168

    
169
void BreakableStatementChecker::VisitForOfStatement(ForOfStatement* stmt) {
170
  // For-of is breakable because of the next() call.
171
  is_breakable_ = true;
172
}
173

    
174

    
175
void BreakableStatementChecker::VisitTryCatchStatement(
176
    TryCatchStatement* stmt) {
177
  // Mark try catch as breakable to avoid adding a break slot in front of it.
178
  is_breakable_ = true;
179
}
180

    
181

    
182
void BreakableStatementChecker::VisitTryFinallyStatement(
183
    TryFinallyStatement* stmt) {
184
  // Mark try finally as breakable to avoid adding a break slot in front of it.
185
  is_breakable_ = true;
186
}
187

    
188

    
189
void BreakableStatementChecker::VisitDebuggerStatement(
190
    DebuggerStatement* stmt) {
191
  // The debugger statement is breakable.
192
  is_breakable_ = true;
193
}
194

    
195

    
196
void BreakableStatementChecker::VisitCaseClause(CaseClause* clause) {
197
}
198

    
199

    
200
void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
201
}
202

    
203

    
204
void BreakableStatementChecker::VisitNativeFunctionLiteral(
205
    NativeFunctionLiteral* expr) {
206
}
207

    
208

    
209
void BreakableStatementChecker::VisitConditional(Conditional* expr) {
210
}
211

    
212

    
213
void BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) {
214
}
215

    
216

    
217
void BreakableStatementChecker::VisitLiteral(Literal* expr) {
218
}
219

    
220

    
221
void BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
222
}
223

    
224

    
225
void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) {
226
}
227

    
228

    
229
void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
230
}
231

    
232

    
233
void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
234
  // If assigning to a property (including a global property) the assignment is
235
  // breakable.
236
  VariableProxy* proxy = expr->target()->AsVariableProxy();
237
  Property* prop = expr->target()->AsProperty();
238
  if (prop != NULL || (proxy != NULL && proxy->var()->IsUnallocated())) {
239
    is_breakable_ = true;
240
    return;
241
  }
242

    
243
  // Otherwise the assignment is breakable if the assigned value is.
244
  Visit(expr->value());
245
}
246

    
247

    
248
void BreakableStatementChecker::VisitYield(Yield* expr) {
249
  // Yield is breakable if the expression is.
250
  Visit(expr->expression());
251
}
252

    
253

    
254
void BreakableStatementChecker::VisitThrow(Throw* expr) {
255
  // Throw is breakable if the expression is.
256
  Visit(expr->exception());
257
}
258

    
259

    
260
void BreakableStatementChecker::VisitProperty(Property* expr) {
261
  // Property load is breakable.
262
  is_breakable_ = true;
263
}
264

    
265

    
266
void BreakableStatementChecker::VisitCall(Call* expr) {
267
  // Function calls both through IC and call stub are breakable.
268
  is_breakable_ = true;
269
}
270

    
271

    
272
void BreakableStatementChecker::VisitCallNew(CallNew* expr) {
273
  // Function calls through new are breakable.
274
  is_breakable_ = true;
275
}
276

    
277

    
278
void BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) {
279
}
280

    
281

    
282
void BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) {
283
  Visit(expr->expression());
284
}
285

    
286

    
287
void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
288
  Visit(expr->expression());
289
}
290

    
291

    
292
void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
293
  Visit(expr->left());
294
  if (expr->op() != Token::AND &&
295
      expr->op() != Token::OR) {
296
    Visit(expr->right());
297
  }
298
}
299

    
300

    
301
void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
302
  Visit(expr->left());
303
  Visit(expr->right());
304
}
305

    
306

    
307
void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
308
}
309

    
310

    
311
#define __ ACCESS_MASM(masm())
312

    
313
bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
314
  Isolate* isolate = info->isolate();
315
  Handle<Script> script = info->script();
316
  if (!script->IsUndefined() && !script->source()->IsUndefined()) {
317
    int len = String::cast(script->source())->length();
318
    isolate->counters()->total_full_codegen_source_size()->Increment(len);
319
  }
320
  CodeGenerator::MakeCodePrologue(info, "full");
321
  const int kInitialBufferSize = 4 * KB;
322
  MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize);
323
#ifdef ENABLE_GDB_JIT_INTERFACE
324
  masm.positions_recorder()->StartGDBJITLineInfoRecording();
325
#endif
326
  LOG_CODE_EVENT(isolate,
327
                 CodeStartLinePosInfoRecordEvent(masm.positions_recorder()));
328

    
329
  FullCodeGenerator cgen(&masm, info);
330
  cgen.Generate();
331
  if (cgen.HasStackOverflow()) {
332
    ASSERT(!isolate->has_pending_exception());
333
    return false;
334
  }
335
  unsigned table_offset = cgen.EmitBackEdgeTable();
336

    
337
  Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
338
  Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
339
  code->set_optimizable(info->IsOptimizable() &&
340
                        !info->function()->dont_optimize() &&
341
                        info->function()->scope()->AllowsLazyCompilation());
342
  cgen.PopulateDeoptimizationData(code);
343
  cgen.PopulateTypeFeedbackInfo(code);
344
  cgen.PopulateTypeFeedbackCells(code);
345
  code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
346
  code->set_handler_table(*cgen.handler_table());
347
#ifdef ENABLE_DEBUGGER_SUPPORT
348
  code->set_compiled_optimizable(info->IsOptimizable());
349
#endif  // ENABLE_DEBUGGER_SUPPORT
350
  code->set_allow_osr_at_loop_nesting_level(0);
351
  code->set_profiler_ticks(0);
352
  code->set_back_edge_table_offset(table_offset);
353
  code->set_back_edges_patched_for_osr(false);
354
  CodeGenerator::PrintCode(code, info);
355
  info->SetCode(code);
356
#ifdef ENABLE_GDB_JIT_INTERFACE
357
  if (FLAG_gdbjit) {
358
    GDBJITLineInfo* lineinfo =
359
        masm.positions_recorder()->DetachGDBJITLineInfo();
360
    GDBJIT(RegisterDetailedLineInfo(*code, lineinfo));
361
  }
362
#endif
363
  void* line_info = masm.positions_recorder()->DetachJITHandlerData();
364
  LOG_CODE_EVENT(isolate, CodeEndLinePosInfoRecordEvent(*code, line_info));
365
  return true;
366
}
367

    
368

    
369
unsigned FullCodeGenerator::EmitBackEdgeTable() {
370
  // The back edge table consists of a length (in number of entries)
371
  // field, and then a sequence of entries.  Each entry is a pair of AST id
372
  // and code-relative pc offset.
373
  masm()->Align(kIntSize);
374
  unsigned offset = masm()->pc_offset();
375
  unsigned length = back_edges_.length();
376
  __ dd(length);
377
  for (unsigned i = 0; i < length; ++i) {
378
    __ dd(back_edges_[i].id.ToInt());
379
    __ dd(back_edges_[i].pc);
380
    __ dd(back_edges_[i].loop_depth);
381
  }
382
  return offset;
383
}
384

    
385

    
386
void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
387
  // Fill in the deoptimization information.
388
  ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
389
  if (!info_->HasDeoptimizationSupport()) return;
390
  int length = bailout_entries_.length();
391
  Handle<DeoptimizationOutputData> data = isolate()->factory()->
392
      NewDeoptimizationOutputData(length, TENURED);
393
  for (int i = 0; i < length; i++) {
394
    data->SetAstId(i, bailout_entries_[i].id);
395
    data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
396
  }
397
  code->set_deoptimization_data(*data);
398
}
399

    
400

    
401
void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
402
  Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo();
403
  info->set_ic_total_count(ic_total_count_);
404
  ASSERT(!isolate()->heap()->InNewSpace(*info));
405
  code->set_type_feedback_info(*info);
406
}
407

    
408

    
409
void FullCodeGenerator::Initialize() {
410
  // The generation of debug code must match between the snapshot code and the
411
  // code that is generated later.  This is assumed by the debugger when it is
412
  // calculating PC offsets after generating a debug version of code.  Therefore
413
  // we disable the production of debug code in the full compiler if we are
414
  // either generating a snapshot or we booted from a snapshot.
415
  generate_debug_code_ = FLAG_debug_code &&
416
                         !Serializer::enabled() &&
417
                         !Snapshot::HaveASnapshotToStartFrom();
418
  masm_->set_emit_debug_code(generate_debug_code_);
419
  masm_->set_predictable_code_size(true);
420
  InitializeAstVisitor(info_->isolate());
421
}
422

    
423

    
424
void FullCodeGenerator::PopulateTypeFeedbackCells(Handle<Code> code) {
425
  if (type_feedback_cells_.is_empty()) return;
426
  int length = type_feedback_cells_.length();
427
  int array_size = TypeFeedbackCells::LengthOfFixedArray(length);
428
  Handle<TypeFeedbackCells> cache = Handle<TypeFeedbackCells>::cast(
429
      isolate()->factory()->NewFixedArray(array_size, TENURED));
430
  for (int i = 0; i < length; i++) {
431
    cache->SetAstId(i, type_feedback_cells_[i].ast_id);
432
    cache->SetCell(i, *type_feedback_cells_[i].cell);
433
  }
434
  TypeFeedbackInfo::cast(code->type_feedback_info())->set_type_feedback_cells(
435
      *cache);
436
}
437

    
438

    
439

    
440
void FullCodeGenerator::PrepareForBailout(Expression* node, State state) {
441
  PrepareForBailoutForId(node->id(), state);
442
}
443

    
444

    
445
void FullCodeGenerator::RecordJSReturnSite(Call* call) {
446
  // We record the offset of the function return so we can rebuild the frame
447
  // if the function was inlined, i.e., this is the return address in the
448
  // inlined function's frame.
449
  //
450
  // The state is ignored.  We defensively set it to TOS_REG, which is the
451
  // real state of the unoptimized code at the return site.
452
  PrepareForBailoutForId(call->ReturnId(), TOS_REG);
453
#ifdef DEBUG
454
  // In debug builds, mark the return so we can verify that this function
455
  // was called.
456
  ASSERT(!call->return_is_recorded_);
457
  call->return_is_recorded_ = true;
458
#endif
459
}
460

    
461

    
462
void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) {
463
  // There's no need to prepare this code for bailouts from already optimized
464
  // code or code that can't be optimized.
465
  if (!info_->HasDeoptimizationSupport()) return;
466
  unsigned pc_and_state =
467
      StateField::encode(state) | PcField::encode(masm_->pc_offset());
468
  ASSERT(Smi::IsValid(pc_and_state));
469
  BailoutEntry entry = { id, pc_and_state };
470
  ASSERT(!prepared_bailout_ids_.Contains(id.ToInt()));
471
  prepared_bailout_ids_.Add(id.ToInt(), zone());
472
  bailout_entries_.Add(entry, zone());
473
}
474

    
475

    
476
void FullCodeGenerator::RecordTypeFeedbackCell(
477
    TypeFeedbackId id, Handle<Cell> cell) {
478
  TypeFeedbackCellEntry entry = { id, cell };
479
  type_feedback_cells_.Add(entry, zone());
480
}
481

    
482

    
483
void FullCodeGenerator::RecordBackEdge(BailoutId ast_id) {
484
  // The pc offset does not need to be encoded and packed together with a state.
485
  ASSERT(masm_->pc_offset() > 0);
486
  ASSERT(loop_depth() > 0);
487
  uint8_t depth = Min(loop_depth(), Code::kMaxLoopNestingMarker);
488
  BackEdgeEntry entry =
489
      { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth };
490
  back_edges_.Add(entry, zone());
491
}
492

    
493

    
494
bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
495
  // Inline smi case inside loops, but not division and modulo which
496
  // are too complicated and take up too much space.
497
  if (op == Token::DIV ||op == Token::MOD) return false;
498
  if (FLAG_always_inline_smi_code) return true;
499
  return loop_depth_ > 0;
500
}
501

    
502

    
503
void FullCodeGenerator::EffectContext::Plug(Register reg) const {
504
}
505

    
506

    
507
void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
508
  __ Move(result_register(), reg);
509
}
510

    
511

    
512
void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
513
  __ Push(reg);
514
}
515

    
516

    
517
void FullCodeGenerator::TestContext::Plug(Register reg) const {
518
  // For simplicity we always test the accumulator register.
519
  __ Move(result_register(), reg);
520
  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
521
  codegen()->DoTest(this);
522
}
523

    
524

    
525
void FullCodeGenerator::EffectContext::PlugTOS() const {
526
  __ Drop(1);
527
}
528

    
529

    
530
void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
531
  __ Pop(result_register());
532
}
533

    
534

    
535
void FullCodeGenerator::StackValueContext::PlugTOS() const {
536
}
537

    
538

    
539
void FullCodeGenerator::TestContext::PlugTOS() const {
540
  // For simplicity we always test the accumulator register.
541
  __ Pop(result_register());
542
  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
543
  codegen()->DoTest(this);
544
}
545

    
546

    
547
void FullCodeGenerator::EffectContext::PrepareTest(
548
    Label* materialize_true,
549
    Label* materialize_false,
550
    Label** if_true,
551
    Label** if_false,
552
    Label** fall_through) const {
553
  // In an effect context, the true and the false case branch to the
554
  // same label.
555
  *if_true = *if_false = *fall_through = materialize_true;
556
}
557

    
558

    
559
void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
560
    Label* materialize_true,
561
    Label* materialize_false,
562
    Label** if_true,
563
    Label** if_false,
564
    Label** fall_through) const {
565
  *if_true = *fall_through = materialize_true;
566
  *if_false = materialize_false;
567
}
568

    
569

    
570
void FullCodeGenerator::StackValueContext::PrepareTest(
571
    Label* materialize_true,
572
    Label* materialize_false,
573
    Label** if_true,
574
    Label** if_false,
575
    Label** fall_through) const {
576
  *if_true = *fall_through = materialize_true;
577
  *if_false = materialize_false;
578
}
579

    
580

    
581
void FullCodeGenerator::TestContext::PrepareTest(
582
    Label* materialize_true,
583
    Label* materialize_false,
584
    Label** if_true,
585
    Label** if_false,
586
    Label** fall_through) const {
587
  *if_true = true_label_;
588
  *if_false = false_label_;
589
  *fall_through = fall_through_;
590
}
591

    
592

    
593
void FullCodeGenerator::DoTest(const TestContext* context) {
594
  DoTest(context->condition(),
595
         context->true_label(),
596
         context->false_label(),
597
         context->fall_through());
598
}
599

    
600

    
601
void FullCodeGenerator::AllocateModules(ZoneList<Declaration*>* declarations) {
602
  ASSERT(scope_->is_global_scope());
603

    
604
  for (int i = 0; i < declarations->length(); i++) {
605
    ModuleDeclaration* declaration = declarations->at(i)->AsModuleDeclaration();
606
    if (declaration != NULL) {
607
      ModuleLiteral* module = declaration->module()->AsModuleLiteral();
608
      if (module != NULL) {
609
        Comment cmnt(masm_, "[ Link nested modules");
610
        Scope* scope = module->body()->scope();
611
        Interface* interface = scope->interface();
612
        ASSERT(interface->IsModule() && interface->IsFrozen());
613

    
614
        interface->Allocate(scope->module_var()->index());
615

    
616
        // Set up module context.
617
        ASSERT(scope->interface()->Index() >= 0);
618
        __ Push(Smi::FromInt(scope->interface()->Index()));
619
        __ Push(scope->GetScopeInfo());
620
        __ CallRuntime(Runtime::kPushModuleContext, 2);
621
        StoreToFrameField(StandardFrameConstants::kContextOffset,
622
                          context_register());
623

    
624
        AllocateModules(scope->declarations());
625

    
626
        // Pop module context.
627
        LoadContextField(context_register(), Context::PREVIOUS_INDEX);
628
        // Update local stack frame context field.
629
        StoreToFrameField(StandardFrameConstants::kContextOffset,
630
                          context_register());
631
      }
632
    }
633
  }
634
}
635

    
636

    
637
// Modules have their own local scope, represented by their own context.
638
// Module instance objects have an accessor for every export that forwards
639
// access to the respective slot from the module's context. (Exports that are
640
// modules themselves, however, are simple data properties.)
641
//
642
// All modules have a _hosting_ scope/context, which (currently) is the
643
// (innermost) enclosing global scope. To deal with recursion, nested modules
644
// are hosted by the same scope as global ones.
645
//
646
// For every (global or nested) module literal, the hosting context has an
647
// internal slot that points directly to the respective module context. This
648
// enables quick access to (statically resolved) module members by 2-dimensional
649
// access through the hosting context. For example,
650
//
651
//   module A {
652
//     let x;
653
//     module B { let y; }
654
//   }
655
//   module C { let z; }
656
//
657
// allocates contexts as follows:
658
//
659
// [header| .A | .B | .C | A | C ]  (global)
660
//           |    |    |
661
//           |    |    +-- [header| z ]  (module)
662
//           |    |
663
//           |    +------- [header| y ]  (module)
664
//           |
665
//           +------------ [header| x | B ]  (module)
666
//
667
// Here, .A, .B, .C are the internal slots pointing to the hosted module
668
// contexts, whereas A, B, C hold the actual instance objects (note that every
669
// module context also points to the respective instance object through its
670
// extension slot in the header).
671
//
672
// To deal with arbitrary recursion and aliases between modules,
673
// they are created and initialized in several stages. Each stage applies to
674
// all modules in the hosting global scope, including nested ones.
675
//
676
// 1. Allocate: for each module _literal_, allocate the module contexts and
677
//    respective instance object and wire them up. This happens in the
678
//    PushModuleContext runtime function, as generated by AllocateModules
679
//    (invoked by VisitDeclarations in the hosting scope).
680
//
681
// 2. Bind: for each module _declaration_ (i.e. literals as well as aliases),
682
//    assign the respective instance object to respective local variables. This
683
//    happens in VisitModuleDeclaration, and uses the instance objects created
684
//    in the previous stage.
685
//    For each module _literal_, this phase also constructs a module descriptor
686
//    for the next stage. This happens in VisitModuleLiteral.
687
//
688
// 3. Populate: invoke the DeclareModules runtime function to populate each
689
//    _instance_ object with accessors for it exports. This is generated by
690
//    DeclareModules (invoked by VisitDeclarations in the hosting scope again),
691
//    and uses the descriptors generated in the previous stage.
692
//
693
// 4. Initialize: execute the module bodies (and other code) in sequence. This
694
//    happens by the separate statements generated for module bodies. To reenter
695
//    the module scopes properly, the parser inserted ModuleStatements.
696

    
697
void FullCodeGenerator::VisitDeclarations(
698
    ZoneList<Declaration*>* declarations) {
699
  Handle<FixedArray> saved_modules = modules_;
700
  int saved_module_index = module_index_;
701
  ZoneList<Handle<Object> >* saved_globals = globals_;
702
  ZoneList<Handle<Object> > inner_globals(10, zone());
703
  globals_ = &inner_globals;
704

    
705
  if (scope_->num_modules() != 0) {
706
    // This is a scope hosting modules. Allocate a descriptor array to pass
707
    // to the runtime for initialization.
708
    Comment cmnt(masm_, "[ Allocate modules");
709
    ASSERT(scope_->is_global_scope());
710
    modules_ =
711
        isolate()->factory()->NewFixedArray(scope_->num_modules(), TENURED);
712
    module_index_ = 0;
713

    
714
    // Generate code for allocating all modules, including nested ones.
715
    // The allocated contexts are stored in internal variables in this scope.
716
    AllocateModules(declarations);
717
  }
718

    
719
  AstVisitor::VisitDeclarations(declarations);
720

    
721
  if (scope_->num_modules() != 0) {
722
    // Initialize modules from descriptor array.
723
    ASSERT(module_index_ == modules_->length());
724
    DeclareModules(modules_);
725
    modules_ = saved_modules;
726
    module_index_ = saved_module_index;
727
  }
728

    
729
  if (!globals_->is_empty()) {
730
    // Invoke the platform-dependent code generator to do the actual
731
    // declaration of the global functions and variables.
732
    Handle<FixedArray> array =
733
       isolate()->factory()->NewFixedArray(globals_->length(), TENURED);
734
    for (int i = 0; i < globals_->length(); ++i)
735
      array->set(i, *globals_->at(i));
736
    DeclareGlobals(array);
737
  }
738

    
739
  globals_ = saved_globals;
740
}
741

    
742

    
743
void FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) {
744
  Block* block = module->body();
745
  Scope* saved_scope = scope();
746
  scope_ = block->scope();
747
  Interface* interface = scope_->interface();
748

    
749
  Comment cmnt(masm_, "[ ModuleLiteral");
750
  SetStatementPosition(block);
751

    
752
  ASSERT(!modules_.is_null());
753
  ASSERT(module_index_ < modules_->length());
754
  int index = module_index_++;
755

    
756
  // Set up module context.
757
  ASSERT(interface->Index() >= 0);
758
  __ Push(Smi::FromInt(interface->Index()));
759
  __ Push(Smi::FromInt(0));
760
  __ CallRuntime(Runtime::kPushModuleContext, 2);
761
  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
762

    
763
  {
764
    Comment cmnt(masm_, "[ Declarations");
765
    VisitDeclarations(scope_->declarations());
766
  }
767

    
768
  // Populate the module description.
769
  Handle<ModuleInfo> description =
770
      ModuleInfo::Create(isolate(), interface, scope_);
771
  modules_->set(index, *description);
772

    
773
  scope_ = saved_scope;
774
  // Pop module context.
775
  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
776
  // Update local stack frame context field.
777
  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
778
}
779

    
780

    
781
void FullCodeGenerator::VisitModuleVariable(ModuleVariable* module) {
782
  // Nothing to do.
783
  // The instance object is resolved statically through the module's interface.
784
}
785

    
786

    
787
void FullCodeGenerator::VisitModulePath(ModulePath* module) {
788
  // Nothing to do.
789
  // The instance object is resolved statically through the module's interface.
790
}
791

    
792

    
793
void FullCodeGenerator::VisitModuleUrl(ModuleUrl* module) {
794
  // TODO(rossberg): dummy allocation for now.
795
  Scope* scope = module->body()->scope();
796
  Interface* interface = scope_->interface();
797

    
798
  ASSERT(interface->IsModule() && interface->IsFrozen());
799
  ASSERT(!modules_.is_null());
800
  ASSERT(module_index_ < modules_->length());
801
  interface->Allocate(scope->module_var()->index());
802
  int index = module_index_++;
803

    
804
  Handle<ModuleInfo> description =
805
      ModuleInfo::Create(isolate(), interface, scope_);
806
  modules_->set(index, *description);
807
}
808

    
809

    
810
int FullCodeGenerator::DeclareGlobalsFlags() {
811
  ASSERT(DeclareGlobalsLanguageMode::is_valid(language_mode()));
812
  return DeclareGlobalsEvalFlag::encode(is_eval()) |
813
      DeclareGlobalsNativeFlag::encode(is_native()) |
814
      DeclareGlobalsLanguageMode::encode(language_mode());
815
}
816

    
817

    
818
void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
819
  CodeGenerator::RecordPositions(masm_, fun->start_position());
820
}
821

    
822

    
823
void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
824
  CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
825
}
826

    
827

    
828
void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
829
#ifdef ENABLE_DEBUGGER_SUPPORT
830
  if (!isolate()->debugger()->IsDebuggerActive()) {
831
    CodeGenerator::RecordPositions(masm_, stmt->position());
832
  } else {
833
    // Check if the statement will be breakable without adding a debug break
834
    // slot.
835
    BreakableStatementChecker checker(isolate());
836
    checker.Check(stmt);
837
    // Record the statement position right here if the statement is not
838
    // breakable. For breakable statements the actual recording of the
839
    // position will be postponed to the breakable code (typically an IC).
840
    bool position_recorded = CodeGenerator::RecordPositions(
841
        masm_, stmt->position(), !checker.is_breakable());
842
    // If the position recording did record a new position generate a debug
843
    // break slot to make the statement breakable.
844
    if (position_recorded) {
845
      Debug::GenerateSlot(masm_);
846
    }
847
  }
848
#else
849
  CodeGenerator::RecordPositions(masm_, stmt->position());
850
#endif
851
}
852

    
853

    
854
void FullCodeGenerator::SetExpressionPosition(Expression* expr) {
855
#ifdef ENABLE_DEBUGGER_SUPPORT
856
  if (!isolate()->debugger()->IsDebuggerActive()) {
857
    CodeGenerator::RecordPositions(masm_, expr->position());
858
  } else {
859
    // Check if the expression will be breakable without adding a debug break
860
    // slot.
861
    BreakableStatementChecker checker(isolate());
862
    checker.Check(expr);
863
    // Record a statement position right here if the expression is not
864
    // breakable. For breakable expressions the actual recording of the
865
    // position will be postponed to the breakable code (typically an IC).
866
    // NOTE this will record a statement position for something which might
867
    // not be a statement. As stepping in the debugger will only stop at
868
    // statement positions this is used for e.g. the condition expression of
869
    // a do while loop.
870
    bool position_recorded = CodeGenerator::RecordPositions(
871
        masm_, expr->position(), !checker.is_breakable());
872
    // If the position recording did record a new position generate a debug
873
    // break slot to make the statement breakable.
874
    if (position_recorded) {
875
      Debug::GenerateSlot(masm_);
876
    }
877
  }
878
#else
879
  CodeGenerator::RecordPositions(masm_, pos);
880
#endif
881
}
882

    
883

    
884
void FullCodeGenerator::SetStatementPosition(int pos) {
885
  CodeGenerator::RecordPositions(masm_, pos);
886
}
887

    
888

    
889
void FullCodeGenerator::SetSourcePosition(int pos) {
890
  if (pos != RelocInfo::kNoPosition) {
891
    masm_->positions_recorder()->RecordPosition(pos);
892
  }
893
}
894

    
895

    
896
// Lookup table for code generators for  special runtime calls which are
897
// generated inline.
898
#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)          \
899
    &FullCodeGenerator::Emit##Name,
900

    
901
const FullCodeGenerator::InlineFunctionGenerator
902
  FullCodeGenerator::kInlineFunctionGenerators[] = {
903
    INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
904
    INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
905
  };
906
#undef INLINE_FUNCTION_GENERATOR_ADDRESS
907

    
908

    
909
FullCodeGenerator::InlineFunctionGenerator
910
  FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
911
    int lookup_index =
912
        static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction);
913
    ASSERT(lookup_index >= 0);
914
    ASSERT(static_cast<size_t>(lookup_index) <
915
           ARRAY_SIZE(kInlineFunctionGenerators));
916
    return kInlineFunctionGenerators[lookup_index];
917
}
918

    
919

    
920
void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
921
  const Runtime::Function* function = expr->function();
922
  ASSERT(function != NULL);
923
  ASSERT(function->intrinsic_type == Runtime::INLINE);
924
  InlineFunctionGenerator generator =
925
      FindInlineFunctionGenerator(function->function_id);
926
  ((*this).*(generator))(expr);
927
}
928

    
929

    
930
void FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) {
931
  ZoneList<Expression*>* args = expr->arguments();
932
  ASSERT(args->length() == 2);
933
  EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::NEXT);
934
}
935

    
936

    
937
void FullCodeGenerator::EmitGeneratorThrow(CallRuntime* expr) {
938
  ZoneList<Expression*>* args = expr->arguments();
939
  ASSERT(args->length() == 2);
940
  EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::THROW);
941
}
942

    
943

    
944
void FullCodeGenerator::EmitDebugBreakInOptimizedCode(CallRuntime* expr) {
945
  context()->Plug(handle(Smi::FromInt(0), isolate()));
946
}
947

    
948

    
949
void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
950
  switch (expr->op()) {
951
    case Token::COMMA:
952
      return VisitComma(expr);
953
    case Token::OR:
954
    case Token::AND:
955
      return VisitLogicalExpression(expr);
956
    default:
957
      return VisitArithmeticExpression(expr);
958
  }
959
}
960

    
961

    
962
void FullCodeGenerator::VisitInDuplicateContext(Expression* expr) {
963
  if (context()->IsEffect()) {
964
    VisitForEffect(expr);
965
  } else if (context()->IsAccumulatorValue()) {
966
    VisitForAccumulatorValue(expr);
967
  } else if (context()->IsStackValue()) {
968
    VisitForStackValue(expr);
969
  } else if (context()->IsTest()) {
970
    const TestContext* test = TestContext::cast(context());
971
    VisitForControl(expr, test->true_label(), test->false_label(),
972
                    test->fall_through());
973
  }
974
}
975

    
976

    
977
void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
978
  Comment cmnt(masm_, "[ Comma");
979
  VisitForEffect(expr->left());
980
  VisitInDuplicateContext(expr->right());
981
}
982

    
983

    
984
void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
985
  bool is_logical_and = expr->op() == Token::AND;
986
  Comment cmnt(masm_, is_logical_and ? "[ Logical AND" :  "[ Logical OR");
987
  Expression* left = expr->left();
988
  Expression* right = expr->right();
989
  BailoutId right_id = expr->RightId();
990
  Label done;
991

    
992
  if (context()->IsTest()) {
993
    Label eval_right;
994
    const TestContext* test = TestContext::cast(context());
995
    if (is_logical_and) {
996
      VisitForControl(left, &eval_right, test->false_label(), &eval_right);
997
    } else {
998
      VisitForControl(left, test->true_label(), &eval_right, &eval_right);
999
    }
1000
    PrepareForBailoutForId(right_id, NO_REGISTERS);
1001
    __ bind(&eval_right);
1002

    
1003
  } else if (context()->IsAccumulatorValue()) {
1004
    VisitForAccumulatorValue(left);
1005
    // We want the value in the accumulator for the test, and on the stack in
1006
    // case we need it.
1007
    __ Push(result_register());
1008
    Label discard, restore;
1009
    if (is_logical_and) {
1010
      DoTest(left, &discard, &restore, &restore);
1011
    } else {
1012
      DoTest(left, &restore, &discard, &restore);
1013
    }
1014
    __ bind(&restore);
1015
    __ Pop(result_register());
1016
    __ jmp(&done);
1017
    __ bind(&discard);
1018
    __ Drop(1);
1019
    PrepareForBailoutForId(right_id, NO_REGISTERS);
1020

    
1021
  } else if (context()->IsStackValue()) {
1022
    VisitForAccumulatorValue(left);
1023
    // We want the value in the accumulator for the test, and on the stack in
1024
    // case we need it.
1025
    __ Push(result_register());
1026
    Label discard;
1027
    if (is_logical_and) {
1028
      DoTest(left, &discard, &done, &discard);
1029
    } else {
1030
      DoTest(left, &done, &discard, &discard);
1031
    }
1032
    __ bind(&discard);
1033
    __ Drop(1);
1034
    PrepareForBailoutForId(right_id, NO_REGISTERS);
1035

    
1036
  } else {
1037
    ASSERT(context()->IsEffect());
1038
    Label eval_right;
1039
    if (is_logical_and) {
1040
      VisitForControl(left, &eval_right, &done, &eval_right);
1041
    } else {
1042
      VisitForControl(left, &done, &eval_right, &eval_right);
1043
    }
1044
    PrepareForBailoutForId(right_id, NO_REGISTERS);
1045
    __ bind(&eval_right);
1046
  }
1047

    
1048
  VisitInDuplicateContext(right);
1049
  __ bind(&done);
1050
}
1051

    
1052

    
1053
void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
1054
  Token::Value op = expr->op();
1055
  Comment cmnt(masm_, "[ ArithmeticExpression");
1056
  Expression* left = expr->left();
1057
  Expression* right = expr->right();
1058
  OverwriteMode mode =
1059
      left->ResultOverwriteAllowed()
1060
      ? OVERWRITE_LEFT
1061
      : (right->ResultOverwriteAllowed() ? OVERWRITE_RIGHT : NO_OVERWRITE);
1062

    
1063
  VisitForStackValue(left);
1064
  VisitForAccumulatorValue(right);
1065

    
1066
  SetSourcePosition(expr->position());
1067
  if (ShouldInlineSmiCase(op)) {
1068
    EmitInlineSmiBinaryOp(expr, op, mode, left, right);
1069
  } else {
1070
    EmitBinaryOp(expr, op, mode);
1071
  }
1072
}
1073

    
1074

    
1075
void FullCodeGenerator::VisitBlock(Block* stmt) {
1076
  Comment cmnt(masm_, "[ Block");
1077
  NestedBlock nested_block(this, stmt);
1078
  SetStatementPosition(stmt);
1079

    
1080
  Scope* saved_scope = scope();
1081
  // Push a block context when entering a block with block scoped variables.
1082
  if (stmt->scope() != NULL) {
1083
    scope_ = stmt->scope();
1084
    ASSERT(!scope_->is_module_scope());
1085
    { Comment cmnt(masm_, "[ Extend block context");
1086
      Handle<ScopeInfo> scope_info = scope_->GetScopeInfo();
1087
      int heap_slots = scope_info->ContextLength() - Context::MIN_CONTEXT_SLOTS;
1088
      __ Push(scope_info);
1089
      PushFunctionArgumentForContextAllocation();
1090
      if (heap_slots <= FastNewBlockContextStub::kMaximumSlots) {
1091
        FastNewBlockContextStub stub(heap_slots);
1092
        __ CallStub(&stub);
1093
      } else {
1094
        __ CallRuntime(Runtime::kPushBlockContext, 2);
1095
      }
1096

    
1097
      // Replace the context stored in the frame.
1098
      StoreToFrameField(StandardFrameConstants::kContextOffset,
1099
                        context_register());
1100
    }
1101
    { Comment cmnt(masm_, "[ Declarations");
1102
      VisitDeclarations(scope_->declarations());
1103
    }
1104
  }
1105

    
1106
  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
1107
  VisitStatements(stmt->statements());
1108
  scope_ = saved_scope;
1109
  __ bind(nested_block.break_label());
1110
  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1111

    
1112
  // Pop block context if necessary.
1113
  if (stmt->scope() != NULL) {
1114
    LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1115
    // Update local stack frame context field.
1116
    StoreToFrameField(StandardFrameConstants::kContextOffset,
1117
                      context_register());
1118
  }
1119
}
1120

    
1121

    
1122
void FullCodeGenerator::VisitModuleStatement(ModuleStatement* stmt) {
1123
  Comment cmnt(masm_, "[ Module context");
1124

    
1125
  __ Push(Smi::FromInt(stmt->proxy()->interface()->Index()));
1126
  __ Push(Smi::FromInt(0));
1127
  __ CallRuntime(Runtime::kPushModuleContext, 2);
1128
  StoreToFrameField(
1129
      StandardFrameConstants::kContextOffset, context_register());
1130

    
1131
  Scope* saved_scope = scope_;
1132
  scope_ = stmt->body()->scope();
1133
  VisitStatements(stmt->body()->statements());
1134
  scope_ = saved_scope;
1135
  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1136
  // Update local stack frame context field.
1137
  StoreToFrameField(StandardFrameConstants::kContextOffset,
1138
                    context_register());
1139
}
1140

    
1141

    
1142
void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
1143
  Comment cmnt(masm_, "[ ExpressionStatement");
1144
  SetStatementPosition(stmt);
1145
  VisitForEffect(stmt->expression());
1146
}
1147

    
1148

    
1149
void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
1150
  Comment cmnt(masm_, "[ EmptyStatement");
1151
  SetStatementPosition(stmt);
1152
}
1153

    
1154

    
1155
void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
1156
  Comment cmnt(masm_, "[ IfStatement");
1157
  SetStatementPosition(stmt);
1158
  Label then_part, else_part, done;
1159

    
1160
  if (stmt->HasElseStatement()) {
1161
    VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
1162
    PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
1163
    __ bind(&then_part);
1164
    Visit(stmt->then_statement());
1165
    __ jmp(&done);
1166

    
1167
    PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
1168
    __ bind(&else_part);
1169
    Visit(stmt->else_statement());
1170
  } else {
1171
    VisitForControl(stmt->condition(), &then_part, &done, &then_part);
1172
    PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
1173
    __ bind(&then_part);
1174
    Visit(stmt->then_statement());
1175

    
1176
    PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
1177
  }
1178
  __ bind(&done);
1179
  PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
1180
}
1181

    
1182

    
1183
void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
1184
  Comment cmnt(masm_,  "[ ContinueStatement");
1185
  SetStatementPosition(stmt);
1186
  NestedStatement* current = nesting_stack_;
1187
  int stack_depth = 0;
1188
  int context_length = 0;
1189
  // When continuing, we clobber the unpredictable value in the accumulator
1190
  // with one that's safe for GC.  If we hit an exit from the try block of
1191
  // try...finally on our way out, we will unconditionally preserve the
1192
  // accumulator on the stack.
1193
  ClearAccumulator();
1194
  while (!current->IsContinueTarget(stmt->target())) {
1195
    current = current->Exit(&stack_depth, &context_length);
1196
  }
1197
  __ Drop(stack_depth);
1198
  if (context_length > 0) {
1199
    while (context_length > 0) {
1200
      LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1201
      --context_length;
1202
    }
1203
    StoreToFrameField(StandardFrameConstants::kContextOffset,
1204
                      context_register());
1205
  }
1206

    
1207
  __ jmp(current->AsIteration()->continue_label());
1208
}
1209

    
1210

    
1211
void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
1212
  Comment cmnt(masm_,  "[ BreakStatement");
1213
  SetStatementPosition(stmt);
1214
  NestedStatement* current = nesting_stack_;
1215
  int stack_depth = 0;
1216
  int context_length = 0;
1217
  // When breaking, we clobber the unpredictable value in the accumulator
1218
  // with one that's safe for GC.  If we hit an exit from the try block of
1219
  // try...finally on our way out, we will unconditionally preserve the
1220
  // accumulator on the stack.
1221
  ClearAccumulator();
1222
  while (!current->IsBreakTarget(stmt->target())) {
1223
    current = current->Exit(&stack_depth, &context_length);
1224
  }
1225
  __ Drop(stack_depth);
1226
  if (context_length > 0) {
1227
    while (context_length > 0) {
1228
      LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1229
      --context_length;
1230
    }
1231
    StoreToFrameField(StandardFrameConstants::kContextOffset,
1232
                      context_register());
1233
  }
1234

    
1235
  __ jmp(current->AsBreakable()->break_label());
1236
}
1237

    
1238

    
1239
void FullCodeGenerator::EmitUnwindBeforeReturn() {
1240
  NestedStatement* current = nesting_stack_;
1241
  int stack_depth = 0;
1242
  int context_length = 0;
1243
  while (current != NULL) {
1244
    current = current->Exit(&stack_depth, &context_length);
1245
  }
1246
  __ Drop(stack_depth);
1247
}
1248

    
1249

    
1250
void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
1251
  Comment cmnt(masm_, "[ ReturnStatement");
1252
  SetStatementPosition(stmt);
1253
  Expression* expr = stmt->expression();
1254
  VisitForAccumulatorValue(expr);
1255
  EmitUnwindBeforeReturn();
1256
  EmitReturnSequence();
1257
}
1258

    
1259

    
1260
void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
1261
  Comment cmnt(masm_, "[ WithStatement");
1262
  SetStatementPosition(stmt);
1263

    
1264
  VisitForStackValue(stmt->expression());
1265
  PushFunctionArgumentForContextAllocation();
1266
  __ CallRuntime(Runtime::kPushWithContext, 2);
1267
  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1268

    
1269
  Scope* saved_scope = scope();
1270
  scope_ = stmt->scope();
1271
  { WithOrCatch body(this);
1272
    Visit(stmt->statement());
1273
  }
1274
  scope_ = saved_scope;
1275

    
1276
  // Pop context.
1277
  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1278
  // Update local stack frame context field.
1279
  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1280
}
1281

    
1282

    
1283
void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
1284
  Comment cmnt(masm_, "[ DoWhileStatement");
1285
  SetStatementPosition(stmt);
1286
  Label body, book_keeping;
1287

    
1288
  Iteration loop_statement(this, stmt);
1289
  increment_loop_depth();
1290

    
1291
  __ bind(&body);
1292
  Visit(stmt->body());
1293

    
1294
  // Record the position of the do while condition and make sure it is
1295
  // possible to break on the condition.
1296
  __ bind(loop_statement.continue_label());
1297
  PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
1298
  SetExpressionPosition(stmt->cond());
1299
  VisitForControl(stmt->cond(),
1300
                  &book_keeping,
1301
                  loop_statement.break_label(),
1302
                  &book_keeping);
1303

    
1304
  // Check stack before looping.
1305
  PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
1306
  __ bind(&book_keeping);
1307
  EmitBackEdgeBookkeeping(stmt, &body);
1308
  __ jmp(&body);
1309

    
1310
  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1311
  __ bind(loop_statement.break_label());
1312
  decrement_loop_depth();
1313
}
1314

    
1315

    
1316
void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1317
  Comment cmnt(masm_, "[ WhileStatement");
1318
  Label test, body;
1319

    
1320
  Iteration loop_statement(this, stmt);
1321
  increment_loop_depth();
1322

    
1323
  // Emit the test at the bottom of the loop.
1324
  __ jmp(&test);
1325

    
1326
  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1327
  __ bind(&body);
1328
  Visit(stmt->body());
1329

    
1330
  // Emit the statement position here as this is where the while
1331
  // statement code starts.
1332
  __ bind(loop_statement.continue_label());
1333
  SetStatementPosition(stmt);
1334

    
1335
  // Check stack before looping.
1336
  EmitBackEdgeBookkeeping(stmt, &body);
1337

    
1338
  __ bind(&test);
1339
  VisitForControl(stmt->cond(),
1340
                  &body,
1341
                  loop_statement.break_label(),
1342
                  loop_statement.break_label());
1343

    
1344
  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1345
  __ bind(loop_statement.break_label());
1346
  decrement_loop_depth();
1347
}
1348

    
1349

    
1350
void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
1351
  Comment cmnt(masm_, "[ ForStatement");
1352
  Label test, body;
1353

    
1354
  Iteration loop_statement(this, stmt);
1355

    
1356
  // Set statement position for a break slot before entering the for-body.
1357
  SetStatementPosition(stmt);
1358

    
1359
  if (stmt->init() != NULL) {
1360
    Visit(stmt->init());
1361
  }
1362

    
1363
  increment_loop_depth();
1364
  // Emit the test at the bottom of the loop (even if empty).
1365
  __ jmp(&test);
1366

    
1367
  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1368
  __ bind(&body);
1369
  Visit(stmt->body());
1370

    
1371
  PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
1372
  __ bind(loop_statement.continue_label());
1373
  if (stmt->next() != NULL) {
1374
    Visit(stmt->next());
1375
  }
1376

    
1377
  // Emit the statement position here as this is where the for
1378
  // statement code starts.
1379
  SetStatementPosition(stmt);
1380

    
1381
  // Check stack before looping.
1382
  EmitBackEdgeBookkeeping(stmt, &body);
1383

    
1384
  __ bind(&test);
1385
  if (stmt->cond() != NULL) {
1386
    VisitForControl(stmt->cond(),
1387
                    &body,
1388
                    loop_statement.break_label(),
1389
                    loop_statement.break_label());
1390
  } else {
1391
    __ jmp(&body);
1392
  }
1393

    
1394
  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1395
  __ bind(loop_statement.break_label());
1396
  decrement_loop_depth();
1397
}
1398

    
1399

    
1400
void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1401
  Comment cmnt(masm_, "[ TryCatchStatement");
1402
  SetStatementPosition(stmt);
1403
  // The try block adds a handler to the exception handler chain before
1404
  // entering, and removes it again when exiting normally.  If an exception
1405
  // is thrown during execution of the try block, the handler is consumed
1406
  // and control is passed to the catch block with the exception in the
1407
  // result register.
1408

    
1409
  Label try_entry, handler_entry, exit;
1410
  __ jmp(&try_entry);
1411
  __ bind(&handler_entry);
1412
  handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
1413
  // Exception handler code, the exception is in the result register.
1414
  // Extend the context before executing the catch block.
1415
  { Comment cmnt(masm_, "[ Extend catch context");
1416
    __ Push(stmt->variable()->name());
1417
    __ Push(result_register());
1418
    PushFunctionArgumentForContextAllocation();
1419
    __ CallRuntime(Runtime::kPushCatchContext, 3);
1420
    StoreToFrameField(StandardFrameConstants::kContextOffset,
1421
                      context_register());
1422
  }
1423

    
1424
  Scope* saved_scope = scope();
1425
  scope_ = stmt->scope();
1426
  ASSERT(scope_->declarations()->is_empty());
1427
  { WithOrCatch catch_body(this);
1428
    Visit(stmt->catch_block());
1429
  }
1430
  // Restore the context.
1431
  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1432
  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1433
  scope_ = saved_scope;
1434
  __ jmp(&exit);
1435

    
1436
  // Try block code. Sets up the exception handler chain.
1437
  __ bind(&try_entry);
1438
  __ PushTryHandler(StackHandler::CATCH, stmt->index());
1439
  { TryCatch try_body(this);
1440
    Visit(stmt->try_block());
1441
  }
1442
  __ PopTryHandler();
1443
  __ bind(&exit);
1444
}
1445

    
1446

    
1447
void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1448
  Comment cmnt(masm_, "[ TryFinallyStatement");
1449
  SetStatementPosition(stmt);
1450
  // Try finally is compiled by setting up a try-handler on the stack while
1451
  // executing the try body, and removing it again afterwards.
1452
  //
1453
  // The try-finally construct can enter the finally block in three ways:
1454
  // 1. By exiting the try-block normally. This removes the try-handler and
1455
  //    calls the finally block code before continuing.
1456
  // 2. By exiting the try-block with a function-local control flow transfer
1457
  //    (break/continue/return). The site of the, e.g., break removes the
1458
  //    try handler and calls the finally block code before continuing
1459
  //    its outward control transfer.
1460
  // 3. By exiting the try-block with a thrown exception.
1461
  //    This can happen in nested function calls. It traverses the try-handler
1462
  //    chain and consumes the try-handler entry before jumping to the
1463
  //    handler code. The handler code then calls the finally-block before
1464
  //    rethrowing the exception.
1465
  //
1466
  // The finally block must assume a return address on top of the stack
1467
  // (or in the link register on ARM chips) and a value (return value or
1468
  // exception) in the result register (rax/eax/r0), both of which must
1469
  // be preserved. The return address isn't GC-safe, so it should be
1470
  // cooked before GC.
1471
  Label try_entry, handler_entry, finally_entry;
1472

    
1473
  // Jump to try-handler setup and try-block code.
1474
  __ jmp(&try_entry);
1475
  __ bind(&handler_entry);
1476
  handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
1477
  // Exception handler code.  This code is only executed when an exception
1478
  // is thrown.  The exception is in the result register, and must be
1479
  // preserved by the finally block.  Call the finally block and then
1480
  // rethrow the exception if it returns.
1481
  __ Call(&finally_entry);
1482
  __ Push(result_register());
1483
  __ CallRuntime(Runtime::kReThrow, 1);
1484

    
1485
  // Finally block implementation.
1486
  __ bind(&finally_entry);
1487
  EnterFinallyBlock();
1488
  { Finally finally_body(this);
1489
    Visit(stmt->finally_block());
1490
  }
1491
  ExitFinallyBlock();  // Return to the calling code.
1492

    
1493
  // Set up try handler.
1494
  __ bind(&try_entry);
1495
  __ PushTryHandler(StackHandler::FINALLY, stmt->index());
1496
  { TryFinally try_body(this, &finally_entry);
1497
    Visit(stmt->try_block());
1498
  }
1499
  __ PopTryHandler();
1500
  // Execute the finally block on the way out.  Clobber the unpredictable
1501
  // value in the result register with one that's safe for GC because the
1502
  // finally block will unconditionally preserve the result register on the
1503
  // stack.
1504
  ClearAccumulator();
1505
  __ Call(&finally_entry);
1506
}
1507

    
1508

    
1509
void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1510
#ifdef ENABLE_DEBUGGER_SUPPORT
1511
  Comment cmnt(masm_, "[ DebuggerStatement");
1512
  SetStatementPosition(stmt);
1513

    
1514
  __ DebugBreak();
1515
  // Ignore the return value.
1516
#endif
1517
}
1518

    
1519

    
1520
void FullCodeGenerator::VisitCaseClause(CaseClause* clause) {
1521
  UNREACHABLE();
1522
}
1523

    
1524

    
1525
void FullCodeGenerator::VisitConditional(Conditional* expr) {
1526
  Comment cmnt(masm_, "[ Conditional");
1527
  Label true_case, false_case, done;
1528
  VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
1529

    
1530
  PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
1531
  __ bind(&true_case);
1532
  SetExpressionPosition(expr->then_expression());
1533
  if (context()->IsTest()) {
1534
    const TestContext* for_test = TestContext::cast(context());
1535
    VisitForControl(expr->then_expression(),
1536
                    for_test->true_label(),
1537
                    for_test->false_label(),
1538
                    NULL);
1539
  } else {
1540
    VisitInDuplicateContext(expr->then_expression());
1541
    __ jmp(&done);
1542
  }
1543

    
1544
  PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
1545
  __ bind(&false_case);
1546
  SetExpressionPosition(expr->else_expression());
1547
  VisitInDuplicateContext(expr->else_expression());
1548
  // If control flow falls through Visit, merge it with true case here.
1549
  if (!context()->IsTest()) {
1550
    __ bind(&done);
1551
  }
1552
}
1553

    
1554

    
1555
void FullCodeGenerator::VisitLiteral(Literal* expr) {
1556
  Comment cmnt(masm_, "[ Literal");
1557
  context()->Plug(expr->value());
1558
}
1559

    
1560

    
1561
void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1562
  Comment cmnt(masm_, "[ FunctionLiteral");
1563

    
1564
  // Build the function boilerplate and instantiate it.
1565
  Handle<SharedFunctionInfo> function_info =
1566
      Compiler::BuildFunctionInfo(expr, script());
1567
  if (function_info.is_null()) {
1568
    SetStackOverflow();
1569
    return;
1570
  }
1571
  EmitNewClosure(function_info, expr->pretenure());
1572
}
1573

    
1574

    
1575
void FullCodeGenerator::VisitNativeFunctionLiteral(
1576
    NativeFunctionLiteral* expr) {
1577
  Comment cmnt(masm_, "[ NativeFunctionLiteral");
1578

    
1579
  // Compute the function template for the native function.
1580
  Handle<String> name = expr->name();
1581
  v8::Handle<v8::FunctionTemplate> fun_template =
1582
      expr->extension()->GetNativeFunction(v8::Utils::ToLocal(name));
1583
  ASSERT(!fun_template.IsEmpty());
1584

    
1585
  // Instantiate the function and create a shared function info from it.
1586
  Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1587
  const int literals = fun->NumberOfLiterals();
1588
  Handle<Code> code = Handle<Code>(fun->shared()->code());
1589
  Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
1590
  bool is_generator = false;
1591
  Handle<SharedFunctionInfo> shared =
1592
      isolate()->factory()->NewSharedFunctionInfo(name, literals, is_generator,
1593
          code, Handle<ScopeInfo>(fun->shared()->scope_info()));
1594
  shared->set_construct_stub(*construct_stub);
1595

    
1596
  // Copy the function data to the shared function info.
1597
  shared->set_function_data(fun->shared()->function_data());
1598
  int parameters = fun->shared()->formal_parameter_count();
1599
  shared->set_formal_parameter_count(parameters);
1600

    
1601
  EmitNewClosure(shared, false);
1602
}
1603

    
1604

    
1605
void FullCodeGenerator::VisitThrow(Throw* expr) {
1606
  Comment cmnt(masm_, "[ Throw");
1607
  VisitForStackValue(expr->exception());
1608
  __ CallRuntime(Runtime::kThrow, 1);
1609
  // Never returns here.
1610
}
1611

    
1612

    
1613
FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
1614
    int* stack_depth,
1615
    int* context_length) {
1616
  // The macros used here must preserve the result register.
1617
  __ Drop(*stack_depth);
1618
  __ PopTryHandler();
1619
  *stack_depth = 0;
1620
  return previous_;
1621
}
1622

    
1623

    
1624
bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
1625
  Expression* sub_expr;
1626
  Handle<String> check;
1627
  if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
1628
    EmitLiteralCompareTypeof(expr, sub_expr, check);
1629
    return true;
1630
  }
1631

    
1632
  if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
1633
    EmitLiteralCompareNil(expr, sub_expr, kUndefinedValue);
1634
    return true;
1635
  }
1636

    
1637
  if (expr->IsLiteralCompareNull(&sub_expr)) {
1638
    EmitLiteralCompareNil(expr, sub_expr, kNullValue);
1639
    return true;
1640
  }
1641

    
1642
  return false;
1643
}
1644

    
1645

    
1646
void BackEdgeTable::Patch(Isolate* isolate,
1647
                          Code* unoptimized) {
1648
  DisallowHeapAllocation no_gc;
1649
  Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement);
1650

    
1651
  // Iterate over the back edge table and patch every interrupt
1652
  // call to an unconditional call to the replacement code.
1653
  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
1654

    
1655
  BackEdgeTable back_edges(unoptimized, &no_gc);
1656
  for (uint32_t i = 0; i < back_edges.length(); i++) {
1657
    if (static_cast<int>(back_edges.loop_depth(i)) == loop_nesting_level) {
1658
      ASSERT_EQ(INTERRUPT, GetBackEdgeState(isolate,
1659
                                            unoptimized,
1660
                                            back_edges.pc(i)));
1661
      PatchAt(unoptimized, back_edges.pc(i), ON_STACK_REPLACEMENT, patch);
1662
    }
1663
  }
1664

    
1665
  unoptimized->set_back_edges_patched_for_osr(true);
1666
  ASSERT(Verify(isolate, unoptimized, loop_nesting_level));
1667
}
1668

    
1669

    
1670
void BackEdgeTable::Revert(Isolate* isolate,
1671
                           Code* unoptimized) {
1672
  DisallowHeapAllocation no_gc;
1673
  Code* patch = isolate->builtins()->builtin(Builtins::kInterruptCheck);
1674

    
1675
  // Iterate over the back edge table and revert the patched interrupt calls.
1676
  ASSERT(unoptimized->back_edges_patched_for_osr());
1677
  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
1678

    
1679
  BackEdgeTable back_edges(unoptimized, &no_gc);
1680
  for (uint32_t i = 0; i < back_edges.length(); i++) {
1681
    if (static_cast<int>(back_edges.loop_depth(i)) <= loop_nesting_level) {
1682
      ASSERT_NE(INTERRUPT, GetBackEdgeState(isolate,
1683
                                            unoptimized,
1684
                                            back_edges.pc(i)));
1685
      PatchAt(unoptimized, back_edges.pc(i), INTERRUPT, patch);
1686
    }
1687
  }
1688

    
1689
  unoptimized->set_back_edges_patched_for_osr(false);
1690
  unoptimized->set_allow_osr_at_loop_nesting_level(0);
1691
  // Assert that none of the back edges are patched anymore.
1692
  ASSERT(Verify(isolate, unoptimized, -1));
1693
}
1694

    
1695

    
1696
void BackEdgeTable::AddStackCheck(CompilationInfo* info) {
1697
  DisallowHeapAllocation no_gc;
1698
  Isolate* isolate = info->isolate();
1699
  Code* code = info->shared_info()->code();
1700
  Address pc = code->instruction_start() + info->osr_pc_offset();
1701
  ASSERT_EQ(ON_STACK_REPLACEMENT, GetBackEdgeState(isolate, code, pc));
1702
  Code* patch = isolate->builtins()->builtin(Builtins::kOsrAfterStackCheck);
1703
  PatchAt(code, pc, OSR_AFTER_STACK_CHECK, patch);
1704
}
1705

    
1706

    
1707
void BackEdgeTable::RemoveStackCheck(CompilationInfo* info) {
1708
  DisallowHeapAllocation no_gc;
1709
  Isolate* isolate = info->isolate();
1710
  Code* code = info->shared_info()->code();
1711
  Address pc = code->instruction_start() + info->osr_pc_offset();
1712
  if (GetBackEdgeState(isolate, code, pc) == OSR_AFTER_STACK_CHECK) {
1713
    Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement);
1714
    PatchAt(code, pc, ON_STACK_REPLACEMENT, patch);
1715
  }
1716
}
1717

    
1718

    
1719
#ifdef DEBUG
1720
bool BackEdgeTable::Verify(Isolate* isolate,
1721
                           Code* unoptimized,
1722
                           int loop_nesting_level) {
1723
  DisallowHeapAllocation no_gc;
1724
  BackEdgeTable back_edges(unoptimized, &no_gc);
1725
  for (uint32_t i = 0; i < back_edges.length(); i++) {
1726
    uint32_t loop_depth = back_edges.loop_depth(i);
1727
    CHECK_LE(static_cast<int>(loop_depth), Code::kMaxLoopNestingMarker);
1728
    // Assert that all back edges for shallower loops (and only those)
1729
    // have already been patched.
1730
    CHECK_EQ((static_cast<int>(loop_depth) <= loop_nesting_level),
1731
             GetBackEdgeState(isolate,
1732
                              unoptimized,
1733
                              back_edges.pc(i)) != INTERRUPT);
1734
  }
1735
  return true;
1736
}
1737
#endif  // DEBUG
1738

    
1739

    
1740
#undef __
1741

    
1742

    
1743
} }  // namespace v8::internal