13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/debug.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/full-codegen.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/liveedit.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/prettyprinter.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopeinfo.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopes.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/snapshot.h"
18d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
19d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkenamespace v8 {
20d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkenamespace internal {
21d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::Check(Statement* stmt) {
237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt);
247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::Check(Expression* expr) {
287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr);
297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid BreakableStatementChecker::VisitVariableDeclaration(
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VariableDeclaration* decl) {
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid BreakableStatementChecker::VisitFunctionDeclaration(
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FunctionDeclaration* decl) {
393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid BreakableStatementChecker::VisitModuleDeclaration(
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ModuleDeclaration* decl) {
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid BreakableStatementChecker::VisitImportDeclaration(
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ImportDeclaration* decl) {
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid BreakableStatementChecker::VisitExportDeclaration(
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExportDeclaration* decl) {
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid BreakableStatementChecker::VisitModuleLiteral(ModuleLiteral* module) {
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid BreakableStatementChecker::VisitModuleVariable(ModuleVariable* module) {
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid BreakableStatementChecker::VisitModulePath(ModulePath* module) {
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid BreakableStatementChecker::VisitModuleUrl(ModuleUrl* module) {
707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BreakableStatementChecker::VisitModuleStatement(ModuleStatement* stmt) {
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitBlock(Block* stmt) {
787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitExpressionStatement(
827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ExpressionStatement* stmt) {
837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check if expression is breakable.
847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->expression());
857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) {
897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) {
937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // If the condition is breakable the if statement is breakable.
947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->condition());
957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitContinueStatement(
997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ContinueStatement* stmt) {
1007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
1047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
1087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Return is breakable if the expression is.
1097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->expression());
1107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
11369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid BreakableStatementChecker::VisitWithStatement(WithStatement* stmt) {
1147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->expression());
1157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
1197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Switch statements breakable if the tag expression is.
1207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->tag());
1217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
1257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark do while as breakable to avoid adding a break slot in front of it.
1267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
1277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) {
1317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark while statements breakable if the condition expression is.
1327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->cond());
1337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
1377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark for statements breakable if the condition expression is.
1387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (stmt->cond() != NULL) {
1397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Visit(stmt->cond());
1407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
1417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
1457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark for in statements breakable if the enumerable expression is.
1467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->enumerable());
1477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BreakableStatementChecker::VisitForOfStatement(ForOfStatement* stmt) {
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For-of is breakable because of the next() call.
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  is_breakable_ = true;
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitTryCatchStatement(
1577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    TryCatchStatement* stmt) {
1587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark try catch as breakable to avoid adding a break slot in front of it.
1597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
1607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitTryFinallyStatement(
1647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    TryFinallyStatement* stmt) {
1657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark try finally as breakable to avoid adding a break slot in front of it.
1667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
1677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitDebuggerStatement(
1717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    DebuggerStatement* stmt) {
1727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // The debugger statement is breakable.
1737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
1747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BreakableStatementChecker::VisitCaseClause(CaseClause* clause) {
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
1827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BreakableStatementChecker::VisitClassLiteral(ClassLiteral* expr) {
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->extends() != NULL) {
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Visit(expr->extends());
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BreakableStatementChecker::VisitNativeFunctionLiteral(
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    NativeFunctionLiteral* expr) {
1947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitConditional(Conditional* expr) {
1987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) {
2027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitLiteral(Literal* expr) {
2067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
2107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) {
2147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
2187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitAssignment(Assignment* expr) {
2227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // If assigning to a property (including a global property) the assignment is
2237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // breakable.
224589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  VariableProxy* proxy = expr->target()->AsVariableProxy();
2257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Property* prop = expr->target()->AsProperty();
226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  if (prop != NULL || (proxy != NULL && proxy->var()->IsUnallocated())) {
2277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    is_breakable_ = true;
2287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    return;
2297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
2307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Otherwise the assignment is breakable if the assigned value is.
2327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->value());
2337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BreakableStatementChecker::VisitYield(Yield* expr) {
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Yield is breakable if the expression is.
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Visit(expr->expression());
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitThrow(Throw* expr) {
2437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Throw is breakable if the expression is.
2447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->exception());
2457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitProperty(Property* expr) {
2497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Property load is breakable.
2507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
2517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitCall(Call* expr) {
2557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Function calls both through IC and call stub are breakable.
2567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
2577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitCallNew(CallNew* expr) {
2617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Function calls through new are breakable.
2627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
2637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) {
2677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) {
2717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->expression());
2727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
2767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->expression());
2777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
2817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->left());
2827d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  if (expr->op() != Token::AND &&
2837d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch      expr->op() != Token::OR) {
2847d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch    Visit(expr->right());
2857d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  }
2867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
2907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->left());
2917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->right());
2927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
2967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BreakableStatementChecker::VisitSuperReference(SuperReference* expr) {}
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
302d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#define __ ACCESS_MASM(masm())
303d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
304f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochbool FullCodeGenerator::MakeCode(CompilationInfo* info) {
30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = info->isolate();
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  TimerEventScope<TimerEventCompileFullCode> timer(info->isolate());
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Handle<Script> script = info->script();
310d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (!script->IsUndefined() && !script->source()->IsUndefined()) {
311d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    int len = String::cast(script->source())->length();
31244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate->counters()->total_full_codegen_source_size()->Increment(len);
313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeGenerator::MakeCodePrologue(info, "full");
315d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const int kInitialBufferSize = 4 * KB;
3168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize);
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (info->will_serialize()) masm.enable_serializer();
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOG_CODE_EVENT(isolate,
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 CodeStartLinePosInfoRecordEvent(masm.positions_recorder()));
321402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FullCodeGenerator cgen(&masm, info);
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cgen.Generate();
324d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (cgen.HasStackOverflow()) {
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!isolate->has_pending_exception());
326f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    return false;
327d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned table_offset = cgen.EmitBackEdgeTable();
329f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
330589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
331f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  code->set_optimizable(info->IsOptimizable() &&
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        !info->function()->dont_optimize() &&
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        info->function()->scope()->AllowsLazyCompilation());
335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  cgen.PopulateDeoptimizationData(code);
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  cgen.PopulateTypeFeedbackInfo(code);
337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  code->set_handler_table(*cgen.handler_table());
3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  code->set_compiled_optimizable(info->IsOptimizable());
340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  code->set_allow_osr_at_loop_nesting_level(0);
3418f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch  code->set_profiler_ticks(0);
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->set_back_edge_table_offset(table_offset);
343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CodeGenerator::PrintCode(code, info);
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info->SetCode(code);
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void* line_info = masm.positions_recorder()->DetachJITHandlerData();
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOG_CODE_EVENT(isolate, CodeEndLinePosInfoRecordEvent(*code, line_info));
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
348d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
350d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochunsigned FullCodeGenerator::EmitBackEdgeTable() {
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The back edge table consists of a length (in number of entries)
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // field, and then a sequence of entries.  Each entry is a pair of AST id
354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // and code-relative pc offset.
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm()->Align(kPointerSize);
356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned offset = masm()->pc_offset();
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned length = back_edges_.length();
358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ dd(length);
359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (unsigned i = 0; i < length; ++i) {
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ dd(back_edges_[i].id.ToInt());
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ dd(back_edges_[i].pc);
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ dd(back_edges_[i].loop_depth);
363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return offset;
365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EnsureSlotContainsAllocationSite(int slot) {
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FixedArray> vector = FeedbackVector();
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!vector->get(slot)->IsAllocationSite()) {
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<AllocationSite> allocation_site =
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->NewAllocationSite();
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    vector->set(slot, *allocation_site);
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Fill in the deoptimization information.
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!info_->HasDeoptimizationSupport()) return;
382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = bailout_entries_.length();
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<DeoptimizationOutputData> data =
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DeoptimizationOutputData::New(isolate(), length, TENURED);
385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; i++) {
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    data->SetAstId(i, bailout_entries_[i].id);
387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  code->set_deoptimization_data(*data);
390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo();
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  info->set_ic_total_count(ic_total_count_);
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!isolate()->heap()->InNewSpace(*info));
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  code->set_type_feedback_info(*info);
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::Initialize() {
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  InitializeAstVisitor(info_->zone());
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The generation of debug code must match between the snapshot code and the
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // code that is generated later.  This is assumed by the debugger when it is
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // calculating PC offsets after generating a debug version of code.  Therefore
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // we disable the production of debug code in the full compiler if we are
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // either generating a snapshot or we booted from a snapshot.
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  generate_debug_code_ = FLAG_debug_code &&
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         !masm_->serializer_enabled() &&
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         !Snapshot::HaveASnapshotToStartFrom();
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm_->set_emit_debug_code(generate_debug_code_);
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  masm_->set_predictable_code_size(true);
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PrepareForBailout(Expression* node, State state) {
417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(node->id(), state);
418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::CallLoadIC(ContextualMode contextual_mode,
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   TypeFeedbackId id) {
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> ic = CodeFactory::LoadIC(isolate(), contextual_mode).code();
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(ic, id);
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::CallStoreIC(TypeFeedbackId id) {
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> ic = CodeFactory::StoreIC(isolate(), strict_mode()).code();
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallIC(ic, id);
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::RecordJSReturnSite(Call* call) {
435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We record the offset of the function return so we can rebuild the frame
436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // if the function was inlined, i.e., this is the return address in the
437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // inlined function's frame.
438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The state is ignored.  We defensively set it to TOS_REG, which is the
440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // real state of the unoptimized code at the return site.
441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(call->ReturnId(), TOS_REG);
442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // In debug builds, mark the return so we can verify that this function
444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // was called.
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!call->return_is_recorded_);
446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  call->return_is_recorded_ = true;
447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) {
452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // There's no need to prepare this code for bailouts from already optimized
453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // code or code that can't be optimized.
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!info_->HasDeoptimizationSupport()) return;
455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned pc_and_state =
456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      StateField::encode(state) | PcField::encode(masm_->pc_offset());
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Smi::IsValid(pc_and_state));
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < bailout_entries_.length(); ++i) {
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(bailout_entries_[i].id != id);
461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BailoutEntry entry = { id, pc_and_state };
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bailout_entries_.Add(entry, zone());
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::RecordBackEdge(BailoutId ast_id) {
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The pc offset does not need to be encoded and packed together with a state.
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(masm_->pc_offset() > 0);
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(loop_depth() > 0);
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  uint8_t depth = Min(loop_depth(), Code::kMaxLoopNestingMarker);
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BackEdgeEntry entry =
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      { ast_id, static_cast<unsigned>(masm_->pc_offset()), depth };
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  back_edges_.Add(entry, zone());
476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
47980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenbool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
48080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Inline smi case inside loops, but not division and modulo which
48180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // are too complicated and take up too much space.
4820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (op == Token::DIV ||op == Token::MOD) return false;
4830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (FLAG_always_inline_smi_code) return true;
4840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return loop_depth_ > 0;
48580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
48680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
48780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4880d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Register reg) const {
4890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4920d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
4930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
4940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4970d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Register reg) const {
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(reg);
4990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5020d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Register reg) const {
5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
5063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
5070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::PlugTOS() const {
5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(1);
5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(result_register());
5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5200d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::PlugTOS() const {
5210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5240d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::PlugTOS() const {
5250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Pop(result_register());
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
5283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  codegen()->DoTest(this);
5290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5320d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::PrepareTest(
5330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
5340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false,
5350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_true,
5360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_false,
5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** fall_through) const {
5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // In an effect context, the true and the false case branch to the
5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // same label.
5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_true = *if_false = *fall_through = materialize_true;
5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::PrepareTest(
5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false,
5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_true,
5480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_false,
5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** fall_through) const {
5500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_true = *fall_through = materialize_true;
5510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_false = materialize_false;
5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5550d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::PrepareTest(
5560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
5570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false,
5580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_true,
5590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_false,
5600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** fall_through) const {
5610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_true = *fall_through = materialize_true;
5620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_false = materialize_false;
5630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5660d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::PrepareTest(
5670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
5680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false,
5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_true,
5700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_false,
5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** fall_through) const {
5720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_true = true_label_;
5730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_false = false_label_;
5740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *fall_through = fall_through_;
57580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
57680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
57780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
5783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(const TestContext* context) {
5793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  DoTest(context->condition(),
5803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         context->true_label(),
5813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         context->false_label(),
5823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch         context->fall_through());
5833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::AllocateModules(ZoneList<Declaration*>* declarations) {
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(scope_->is_global_scope());
5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < declarations->length(); i++) {
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ModuleDeclaration* declaration = declarations->at(i)->AsModuleDeclaration();
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (declaration != NULL) {
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ModuleLiteral* module = declaration->module()->AsModuleLiteral();
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (module != NULL) {
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Comment cmnt(masm_, "[ Link nested modules");
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Scope* scope = module->body()->scope();
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Interface* interface = scope->interface();
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(interface->IsModule() && interface->IsFrozen());
598d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        interface->Allocate(scope->module_var()->index());
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Set up module context.
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(scope->interface()->Index() >= 0);
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Push(Smi::FromInt(scope->interface()->Index()));
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ Push(scope->GetScopeInfo());
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        __ CallRuntime(Runtime::kPushModuleContext, 2);
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        StoreToFrameField(StandardFrameConstants::kContextOffset,
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          context_register());
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        AllocateModules(scope->declarations());
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Pop module context.
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        LoadContextField(context_register(), Context::PREVIOUS_INDEX);
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Update local stack frame context field.
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        StoreToFrameField(StandardFrameConstants::kContextOffset,
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          context_register());
616d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      }
617d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
618d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Modules have their own local scope, represented by their own context.
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Module instance objects have an accessor for every export that forwards
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// access to the respective slot from the module's context. (Exports that are
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// modules themselves, however, are simple data properties.)
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// All modules have a _hosting_ scope/context, which (currently) is the
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// (innermost) enclosing global scope. To deal with recursion, nested modules
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// are hosted by the same scope as global ones.
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// For every (global or nested) module literal, the hosting context has an
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// internal slot that points directly to the respective module context. This
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// enables quick access to (statically resolved) module members by 2-dimensional
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// access through the hosting context. For example,
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   module A {
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     let x;
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     module B { let y; }
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   }
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//   module C { let z; }
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// allocates contexts as follows:
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// [header| .A | .B | .C | A | C ]  (global)
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//           |    |    |
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//           |    |    +-- [header| z ]  (module)
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//           |    |
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//           |    +------- [header| y ]  (module)
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//           |
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//           +------------ [header| x | B ]  (module)
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Here, .A, .B, .C are the internal slots pointing to the hosted module
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// contexts, whereas A, B, C hold the actual instance objects (note that every
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// module context also points to the respective instance object through its
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// extension slot in the header).
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// To deal with arbitrary recursion and aliases between modules,
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// they are created and initialized in several stages. Each stage applies to
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// all modules in the hosting global scope, including nested ones.
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 1. Allocate: for each module _literal_, allocate the module contexts and
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    respective instance object and wire them up. This happens in the
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    PushModuleContext runtime function, as generated by AllocateModules
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    (invoked by VisitDeclarations in the hosting scope).
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 2. Bind: for each module _declaration_ (i.e. literals as well as aliases),
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    assign the respective instance object to respective local variables. This
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    happens in VisitModuleDeclaration, and uses the instance objects created
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    in the previous stage.
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    For each module _literal_, this phase also constructs a module descriptor
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    for the next stage. This happens in VisitModuleLiteral.
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 3. Populate: invoke the DeclareModules runtime function to populate each
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    _instance_ object with accessors for it exports. This is generated by
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    DeclareModules (invoked by VisitDeclarations in the hosting scope again),
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    and uses the descriptors generated in the previous stage.
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 4. Initialize: execute the module bodies (and other code) in sequence. This
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    happens by the separate statements generated for module bodies. To reenter
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    the module scopes properly, the parser inserted ModuleStatements.
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitDeclarations(
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ZoneList<Declaration*>* declarations) {
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<FixedArray> saved_modules = modules_;
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int saved_module_index = module_index_;
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Handle<Object> >* saved_globals = globals_;
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Handle<Object> > inner_globals(10, zone());
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  globals_ = &inner_globals;
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (scope_->num_modules() != 0) {
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // This is a scope hosting modules. Allocate a descriptor array to pass
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // to the runtime for initialization.
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Allocate modules");
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(scope_->is_global_scope());
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    modules_ =
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate()->factory()->NewFixedArray(scope_->num_modules(), TENURED);
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    module_index_ = 0;
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Generate code for allocating all modules, including nested ones.
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The allocated contexts are stored in internal variables in this scope.
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    AllocateModules(declarations);
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  AstVisitor::VisitDeclarations(declarations);
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (scope_->num_modules() != 0) {
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Initialize modules from descriptor array.
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(module_index_ == modules_->length());
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeclareModules(modules_);
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    modules_ = saved_modules;
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    module_index_ = saved_module_index;
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
7133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!globals_->is_empty()) {
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Invoke the platform-dependent code generator to do the actual
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // declaration of the global functions and variables.
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<FixedArray> array =
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       isolate()->factory()->NewFixedArray(globals_->length(), TENURED);
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = 0; i < globals_->length(); ++i)
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      array->set(i, *globals_->at(i));
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeclareGlobals(array);
722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
7233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  globals_ = saved_globals;
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitModuleLiteral(ModuleLiteral* module) {
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Block* block = module->body();
730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Scope* saved_scope = scope();
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  scope_ = block->scope();
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Interface* interface = scope_->interface();
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ ModuleLiteral");
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetStatementPosition(block);
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!modules_.is_null());
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(module_index_ < modules_->length());
739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int index = module_index_++;
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set up module context.
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(interface->Index() >= 0);
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Smi::FromInt(interface->Index()));
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Smi::FromInt(0));
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kPushModuleContext, 2);
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Comment cmnt(masm_, "[ Declarations");
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitDeclarations(scope_->declarations());
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Populate the module description.
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<ModuleInfo> description =
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ModuleInfo::Create(isolate(), interface, scope_);
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  modules_->set(index, *description);
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  scope_ = saved_scope;
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Pop module context.
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update local stack frame context field.
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::VisitModuleVariable(ModuleVariable* module) {
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Nothing to do.
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The instance object is resolved statically through the module's interface.
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::VisitModulePath(ModulePath* module) {
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Nothing to do.
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The instance object is resolved statically through the module's interface.
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitModuleUrl(ModuleUrl* module) {
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(rossberg): dummy allocation for now.
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Scope* scope = module->body()->scope();
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Interface* interface = scope_->interface();
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(interface->IsModule() && interface->IsFrozen());
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!modules_.is_null());
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(module_index_ < modules_->length());
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  interface->Allocate(scope->module_var()->index());
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int index = module_index_++;
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<ModuleInfo> description =
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ModuleInfo::Create(isolate(), interface, scope_);
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  modules_->set(index, *description);
792d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
793d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
794d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
795589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochint FullCodeGenerator::DeclareGlobalsFlags() {
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(DeclareGlobalsStrictMode::is_valid(strict_mode()));
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return DeclareGlobalsEvalFlag::encode(is_eval()) |
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      DeclareGlobalsNativeFlag::encode(is_native()) |
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DeclareGlobalsStrictMode::encode(strict_mode());
800589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch}
801589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
802589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
803d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
8043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CodeGenerator::RecordPositions(masm_, fun->start_position());
805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
808d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
8093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
810d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
811d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
812d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
813d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::SetStatementPosition(Statement* stmt) {
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!info_->is_debug()) {
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodeGenerator::RecordPositions(masm_, stmt->position());
8163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
8173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check if the statement will be breakable without adding a debug break
8183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // slot.
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BreakableStatementChecker checker(zone());
8203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    checker.Check(stmt);
8213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Record the statement position right here if the statement is not
8223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // breakable. For breakable statements the actual recording of the
8233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // position will be postponed to the breakable code (typically an IC).
8243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool position_recorded = CodeGenerator::RecordPositions(
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        masm_, stmt->position(), !checker.is_breakable());
8263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // If the position recording did record a new position generate a debug
8273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // break slot to make the statement breakable.
8283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (position_recorded) {
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DebugCodegen::GenerateSlot(masm_);
8307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
8313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
8327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
8337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
8347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitSuperReference(SuperReference* super) {
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::SetExpressionPosition(Expression* expr) {
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!info_->is_debug()) {
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodeGenerator::RecordPositions(masm_, expr->position());
8433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
8443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Check if the expression will be breakable without adding a debug break
8453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // slot.
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BreakableStatementChecker checker(zone());
8473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    checker.Check(expr);
8483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Record a statement position right here if the expression is not
8493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // breakable. For breakable expressions the actual recording of the
8503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // position will be postponed to the breakable code (typically an IC).
8513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // NOTE this will record a statement position for something which might
8523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // not be a statement. As stepping in the debugger will only stop at
8533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // statement positions this is used for e.g. the condition expression of
8543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // a do while loop.
8553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool position_recorded = CodeGenerator::RecordPositions(
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        masm_, expr->position(), !checker.is_breakable());
8573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // If the position recording did record a new position generate a debug
8583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // break slot to make the statement breakable.
8593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (position_recorded) {
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DebugCodegen::GenerateSlot(masm_);
8617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
8623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
863d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
864d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
865d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::SetSourcePosition(int pos) {
8673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (pos != RelocInfo::kNoPosition) {
868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    masm_->positions_recorder()->RecordPosition(pos);
869d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
870d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
871d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
872d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
8730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen// Lookup table for code generators for  special runtime calls which are
8740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen// generated inline.
8750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)          \
8760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    &FullCodeGenerator::Emit##Name,
877791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
8780d5e116f6aee03185f237311a943491bb079a768Kristian Monsenconst FullCodeGenerator::InlineFunctionGenerator
8790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  FullCodeGenerator::kInlineFunctionGenerators[] = {
8800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
8810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  };
8820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#undef INLINE_FUNCTION_GENERATOR_ADDRESS
8830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
8840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
8850d5e116f6aee03185f237311a943491bb079a768Kristian MonsenFullCodeGenerator::InlineFunctionGenerator
8860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int lookup_index =
888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction);
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(lookup_index >= 0);
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(static_cast<size_t>(lookup_index) <
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           arraysize(kInlineFunctionGenerators));
892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return kInlineFunctionGenerators[lookup_index];
8930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
8940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
8950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const Runtime::Function* function = expr->function();
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(function != NULL);
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(function->intrinsic_type == Runtime::INLINE);
9000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  InlineFunctionGenerator generator =
9010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      FindInlineFunctionGenerator(function->function_id);
9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ((*this).*(generator))(expr);
90380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
90480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
90580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitGeneratorNext(CallRuntime* expr) {
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::NEXT);
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitGeneratorThrow(CallRuntime* expr) {
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Expression*>* args = expr->arguments();
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(args->length() == 2);
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitGeneratorResume(args->at(0), args->at(1), JSGeneratorObject::THROW);
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugBreakInOptimizedCode(CallRuntime* expr) {
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(handle(Smi::FromInt(0), isolate()));
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
9263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  switch (expr->op()) {
92780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::COMMA:
9283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return VisitComma(expr);
92980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::OR:
93080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::AND:
9313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return VisitLogicalExpression(expr);
93280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
9333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return VisitArithmeticExpression(expr);
93480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
9357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
9367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
9377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::VisitInDuplicateContext(Expression* expr) {
9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (context()->IsEffect()) {
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForEffect(expr);
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (context()->IsAccumulatorValue()) {
9423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForAccumulatorValue(expr);
9433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (context()->IsStackValue()) {
9443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForStackValue(expr);
9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else if (context()->IsTest()) {
9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const TestContext* test = TestContext::cast(context());
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitForControl(expr, test->true_label(), test->false_label(),
9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    test->fall_through());
9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::VisitComma(BinaryOperation* expr) {
9543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Comment cmnt(masm_, "[ Comma");
9553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  VisitForEffect(expr->left());
9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitInDuplicateContext(expr->right());
957d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
958d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
959d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
9603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
9613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  bool is_logical_and = expr->op() == Token::AND;
9623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Comment cmnt(masm_, is_logical_and ? "[ Logical AND" :  "[ Logical OR");
9633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Expression* left = expr->left();
9643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Expression* right = expr->right();
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BailoutId right_id = expr->RightId();
9663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Label done;
9670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
9683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (context()->IsTest()) {
9693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Label eval_right;
9703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    const TestContext* test = TestContext::cast(context());
9713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (is_logical_and) {
9723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForControl(left, &eval_right, test->false_label(), &eval_right);
9733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
9743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForControl(left, test->true_label(), &eval_right, &eval_right);
9753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
9763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    PrepareForBailoutForId(right_id, NO_REGISTERS);
9773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ bind(&eval_right);
9783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (context()->IsAccumulatorValue()) {
9803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    VisitForAccumulatorValue(left);
9813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // We want the value in the accumulator for the test, and on the stack in
9823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // case we need it.
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(result_register());
9843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Label discard, restore;
9853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (is_logical_and) {
9863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      DoTest(left, &discard, &restore, &restore);
9873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
9883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      DoTest(left, &restore, &discard, &restore);
9893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
9903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ bind(&restore);
991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Pop(result_register());
9923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ jmp(&done);
9933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ bind(&discard);
9943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Drop(1);
9953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    PrepareForBailoutForId(right_id, NO_REGISTERS);
9963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else if (context()->IsStackValue()) {
9983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    VisitForAccumulatorValue(left);
9993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // We want the value in the accumulator for the test, and on the stack in
10003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // case we need it.
1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(result_register());
10023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Label discard;
10033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (is_logical_and) {
10043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      DoTest(left, &discard, &done, &discard);
10053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
10063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      DoTest(left, &done, &discard, &discard);
10073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
10083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ bind(&discard);
10093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Drop(1);
10103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    PrepareForBailoutForId(right_id, NO_REGISTERS);
10110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
10120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(context()->IsEffect());
10143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Label eval_right;
10153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (is_logical_and) {
10163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForControl(left, &eval_right, &done, &eval_right);
10173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
10183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      VisitForControl(left, &done, &eval_right, &eval_right);
10193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
10203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    PrepareForBailoutForId(right_id, NO_REGISTERS);
10213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ bind(&eval_right);
10220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
10233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitInDuplicateContext(right);
10253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ bind(&done);
10260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
10270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
102880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
10293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
10303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Token::Value op = expr->op();
10313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Comment cmnt(masm_, "[ ArithmeticExpression");
10323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Expression* left = expr->left();
10333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Expression* right = expr->right();
10343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  OverwriteMode mode =
10353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      left->ResultOverwriteAllowed()
10363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ? OVERWRITE_LEFT
10373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      : (right->ResultOverwriteAllowed() ? OVERWRITE_RIGHT : NO_OVERWRITE);
103880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
10393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  VisitForStackValue(left);
10403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  VisitForAccumulatorValue(right);
104180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
10423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SetSourcePosition(expr->position());
10433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (ShouldInlineSmiCase(op)) {
10443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    EmitInlineSmiBinaryOp(expr, op, mode, left, right);
10450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
10463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    EmitBinaryOp(expr, op, mode);
10470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
10480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
10490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
10500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
1051d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBlock(Block* stmt) {
1052d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ Block");
1053589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  NestedBlock nested_block(this, stmt);
1054d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
105669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Scope* saved_scope = scope();
1057589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Push a block context when entering a block with block scoped variables.
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (stmt->scope() == NULL) {
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } else {
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    scope_ = stmt->scope();
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!scope_->is_module_scope());
106369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    { Comment cmnt(masm_, "[ Extend block context");
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ Push(scope_->GetScopeInfo());
106569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      PushFunctionArgumentForContextAllocation();
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      __ CallRuntime(Runtime::kPushBlockContext, 2);
10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Replace the context stored in the frame.
106969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      StoreToFrameField(StandardFrameConstants::kContextOffset,
107069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                        context_register());
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
107269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
107369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    { Comment cmnt(masm_, "[ Declarations");
107469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      VisitDeclarations(scope_->declarations());
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrepareForBailoutForId(stmt->DeclsId(), NO_REGISTERS);
107669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
107769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1079d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  VisitStatements(stmt->statements());
108069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  scope_ = saved_scope;
1081589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  __ bind(nested_block.break_label());
1082589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
1083589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Pop block context if necessary.
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (stmt->scope() != NULL) {
1085589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1086589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    // Update local stack frame context field.
1087589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch    StoreToFrameField(StandardFrameConstants::kContextOffset,
1088589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch                      context_register());
1089589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  }
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitModuleStatement(ModuleStatement* stmt) {
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ Module context");
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Smi::FromInt(stmt->proxy()->interface()->Index()));
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(Smi::FromInt(0));
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ CallRuntime(Runtime::kPushModuleContext, 2);
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreToFrameField(
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      StandardFrameConstants::kContextOffset, context_register());
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Scope* saved_scope = scope_;
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  scope_ = stmt->body()->scope();
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitStatements(stmt->body()->statements());
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  scope_ = saved_scope;
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Update local stack frame context field.
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  StoreToFrameField(StandardFrameConstants::kContextOffset,
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    context_register());
1111d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1112d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1113d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
1115d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ ExpressionStatement");
1116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1117d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  VisitForEffect(stmt->expression());
1118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1119d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1120d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
1122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ EmptyStatement");
1123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1124d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1125d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1126d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1127d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
1128d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ IfStatement");
1129d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1130d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label then_part, else_part, done;
1131d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
113280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (stmt->HasElseStatement()) {
113380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
113580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ bind(&then_part);
113680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Visit(stmt->then_statement());
113780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ jmp(&done);
1138d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
114080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ bind(&else_part);
114180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Visit(stmt->else_statement());
114280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
114380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    VisitForControl(stmt->condition(), &then_part, &done, &then_part);
1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
114580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ bind(&then_part);
114680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Visit(stmt->then_statement());
1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
114980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
1150d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
11513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
1152d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1153d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1154d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1155d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
1156d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_,  "[ ContinueStatement");
1157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1158d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  NestedStatement* current = nesting_stack_;
1159d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int stack_depth = 0;
116069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int context_length = 0;
1161db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // When continuing, we clobber the unpredictable value in the accumulator
1162db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // with one that's safe for GC.  If we hit an exit from the try block of
1163db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // try...finally on our way out, we will unconditionally preserve the
1164db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // accumulator on the stack.
1165db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  ClearAccumulator();
1166d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  while (!current->IsContinueTarget(stmt->target())) {
116769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    current = current->Exit(&stack_depth, &context_length);
1168d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1169d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Drop(stack_depth);
117069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (context_length > 0) {
117169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    while (context_length > 0) {
117269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      LoadContextField(context_register(), Context::PREVIOUS_INDEX);
117369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      --context_length;
117469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
117569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    StoreToFrameField(StandardFrameConstants::kContextOffset,
117669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                      context_register());
117769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
1178d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
117969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ jmp(current->AsIteration()->continue_label());
1180d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1181d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1182d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1183d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
1184d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_,  "[ BreakStatement");
1185d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1186d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  NestedStatement* current = nesting_stack_;
1187d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int stack_depth = 0;
118869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int context_length = 0;
1189db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // When breaking, we clobber the unpredictable value in the accumulator
1190db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // with one that's safe for GC.  If we hit an exit from the try block of
1191db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // try...finally on our way out, we will unconditionally preserve the
1192db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // accumulator on the stack.
1193db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  ClearAccumulator();
1194d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  while (!current->IsBreakTarget(stmt->target())) {
119569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    current = current->Exit(&stack_depth, &context_length);
1196d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1197d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Drop(stack_depth);
119869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  if (context_length > 0) {
119969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    while (context_length > 0) {
120069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      LoadContextField(context_register(), Context::PREVIOUS_INDEX);
120169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      --context_length;
120269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
120369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    StoreToFrameField(StandardFrameConstants::kContextOffset,
120469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                      context_register());
120569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
1206d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
120769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ jmp(current->AsBreakable()->break_label());
1208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1210d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitUnwindBeforeReturn() {
1212d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  NestedStatement* current = nesting_stack_;
1213d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int stack_depth = 0;
121469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int context_length = 0;
1215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  while (current != NULL) {
121669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    current = current->Exit(&stack_depth, &context_length);
1217d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1218d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Drop(stack_depth);
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1220d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ ReturnStatement");
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetStatementPosition(stmt);
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Expression* expr = stmt->expression();
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForAccumulatorValue(expr);
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitUnwindBeforeReturn();
12287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  EmitReturnSequence();
1229d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1230d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1231d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
123269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
123369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Comment cmnt(masm_, "[ WithStatement");
1234d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1235d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
12360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->expression());
12373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  PushFunctionArgumentForContextAllocation();
12383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  __ CallRuntime(Runtime::kPushWithContext, 2);
123969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
124069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Scope* saved_scope = scope();
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  scope_ = stmt->scope();
124369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  { WithOrCatch body(this);
124469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Visit(stmt->statement());
124569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  scope_ = saved_scope;
124769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
124869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Pop context.
124969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
125069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Update local stack frame context field.
1251d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1252d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1253d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1255d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
1256d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ DoWhileStatement");
1257d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label body, book_keeping;
1259d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1260d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Iteration loop_statement(this, stmt);
1261d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  increment_loop_depth();
1262d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1263d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&body);
1264d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Visit(stmt->body());
1265d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
126680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Record the position of the do while condition and make sure it is
126780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // possible to break on the condition.
126869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.continue_label());
1269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetExpressionPosition(stmt->cond());
127180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VisitForControl(stmt->cond(),
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &book_keeping,
127369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                  loop_statement.break_label(),
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &book_keeping);
12757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check stack before looping.
1277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&book_keeping);
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBackEdgeBookkeeping(stmt, &body);
1280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ jmp(&body);
1281d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
128369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.break_label());
1284d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  decrement_loop_depth();
1285d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1286d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1287d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1288d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1289d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ WhileStatement");
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label loop, body;
1291d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1292d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Iteration loop_statement(this, stmt);
1293d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  increment_loop_depth();
1294d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&loop);
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetExpressionPosition(stmt->cond());
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  VisitForControl(stmt->cond(),
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &body,
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  loop_statement.break_label(),
1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  &body);
1302d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1304d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&body);
1305d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Visit(stmt->body());
130680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
130769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.continue_label());
1308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check stack before looping.
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBackEdgeBookkeeping(stmt, &loop);
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&loop);
1312d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
131469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.break_label());
1315d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  decrement_loop_depth();
1316d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1317d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1318d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1319d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
1320d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ ForStatement");
1321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label test, body;
1322d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1323d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Iteration loop_statement(this, stmt);
13243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set statement position for a break slot before entering the for-body.
13263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SetStatementPosition(stmt);
13273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1328d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (stmt->init() != NULL) {
1329d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Visit(stmt->init());
1330d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1331d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1332d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  increment_loop_depth();
1333d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Emit the test at the bottom of the loop (even if empty).
1334d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ jmp(&test);
1335d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1337d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&body);
1338d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Visit(stmt->body());
1339d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
134169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.continue_label());
1342d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (stmt->next() != NULL) {
1343d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Visit(stmt->next());
1344d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1345d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
134680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Emit the statement position here as this is where the for
134780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // statement code starts.
13487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetStatementPosition(stmt);
1349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1350d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check stack before looping.
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitBackEdgeBookkeeping(stmt, &body);
1352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&test);
1354d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (stmt->cond() != NULL) {
135580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    VisitForControl(stmt->cond(),
135680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    &body,
135769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                    loop_statement.break_label(),
135869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                    loop_statement.break_label());
1359d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else {
1360d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ jmp(&body);
1361d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1362d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
136469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(loop_statement.break_label());
1365d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  decrement_loop_depth();
1366d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1367d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1368d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1369d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1370d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ TryCatchStatement");
1371d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The try block adds a handler to the exception handler chain before
13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // entering, and removes it again when exiting normally.  If an exception
13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // is thrown during execution of the try block, the handler is consumed
13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // and control is passed to the catch block with the exception in the
13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // result register.
13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label try_entry, handler_entry, exit;
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&try_entry);
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&handler_entry);
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Exception handler code, the exception is in the result register.
13833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Extend the context before executing the catch block.
13843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  { Comment cmnt(masm_, "[ Extend catch context");
13853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ Push(stmt->variable()->name());
1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Push(result_register());
13873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    PushFunctionArgumentForContextAllocation();
13883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    __ CallRuntime(Runtime::kPushCatchContext, 3);
13893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    StoreToFrameField(StandardFrameConstants::kContextOffset,
13903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                      context_register());
1391d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1392d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
13933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Scope* saved_scope = scope();
13943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  scope_ = stmt->scope();
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(scope_->declarations()->is_empty());
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  { WithOrCatch catch_body(this);
139769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Visit(stmt->catch_block());
139869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
1399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  // Restore the context.
1400589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1401589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
14023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  scope_ = saved_scope;
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&exit);
1404d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1405d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Try block code. Sets up the exception handler chain.
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&try_entry);
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ PushTryHandler(StackHandler::CATCH, stmt->index());
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  { TryCatch try_body(this);
1409d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Visit(stmt->try_block());
1410d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ PopTryHandler();
14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&exit);
1413d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1414d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1415d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1416d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1417d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ TryFinallyStatement");
1418d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1419d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Try finally is compiled by setting up a try-handler on the stack while
1420d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // executing the try body, and removing it again afterwards.
1421d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //
1422d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The try-finally construct can enter the finally block in three ways:
1423d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // 1. By exiting the try-block normally. This removes the try-handler and
14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //    calls the finally block code before continuing.
1425d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // 2. By exiting the try-block with a function-local control flow transfer
1426d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    (break/continue/return). The site of the, e.g., break removes the
1427d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    try handler and calls the finally block code before continuing
1428d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    its outward control transfer.
14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // 3. By exiting the try-block with a thrown exception.
1430d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    This can happen in nested function calls. It traverses the try-handler
1431d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    chain and consumes the try-handler entry before jumping to the
1432d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    handler code. The handler code then calls the finally-block before
1433d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    rethrowing the exception.
1434d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //
1435d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The finally block must assume a return address on top of the stack
1436d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // (or in the link register on ARM chips) and a value (return value or
1437d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // exception) in the result register (rax/eax/r0), both of which must
1438d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // be preserved. The return address isn't GC-safe, so it should be
1439d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // cooked before GC.
14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Label try_entry, handler_entry, finally_entry;
14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Jump to try-handler setup and try-block code.
14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ jmp(&try_entry);
14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&handler_entry);
14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  handler_table()->set(stmt->index(), Smi::FromInt(handler_entry.pos()));
14463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Exception handler code.  This code is only executed when an exception
14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // is thrown.  The exception is in the result register, and must be
14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // preserved by the finally block.  Call the finally block and then
14493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // rethrow the exception if it returns.
14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ Call(&finally_entry);
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ Push(result_register());
14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ CallRuntime(Runtime::kReThrow, 1);
1453d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Finally block implementation.
1455d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&finally_entry);
14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  EnterFinallyBlock();
14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  { Finally finally_body(this);
1458d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Visit(stmt->finally_block());
1459d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ExitFinallyBlock();  // Return to the calling code.
1461d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up try handler.
14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ bind(&try_entry);
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ PushTryHandler(StackHandler::FINALLY, stmt->index());
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  { TryFinally try_body(this, &finally_entry);
1466d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Visit(stmt->try_block());
1467d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ PopTryHandler();
1469db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // Execute the finally block on the way out.  Clobber the unpredictable
14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // value in the result register with one that's safe for GC because the
14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // finally block will unconditionally preserve the result register on the
14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // stack.
1473db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  ClearAccumulator();
1474d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Call(&finally_entry);
1475d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1476d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1477d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1478d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1479d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ DebuggerStatement");
1480d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
14814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
1482402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ DebugBreak();
1483d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Ignore the return value.
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PrepareForBailoutForId(stmt->DebugBreakId(), NO_REGISTERS);
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitCaseClause(CaseClause* clause) {
1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UNREACHABLE();
1491d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1492d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1494d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitConditional(Conditional* expr) {
1495d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ Conditional");
1496d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label true_case, false_case, done;
149780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
1498d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
1500d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&true_case);
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetExpressionPosition(expr->then_expression());
1502f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (context()->IsTest()) {
1503f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    const TestContext* for_test = TestContext::cast(context());
1504f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    VisitForControl(expr->then_expression(),
1505f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                    for_test->true_label(),
1506f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                    for_test->false_label(),
1507f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                    NULL);
1508f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  } else {
15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    VisitInDuplicateContext(expr->then_expression());
1510d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ jmp(&done);
1511d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1512d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
1514d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&false_case);
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetExpressionPosition(expr->else_expression());
15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VisitInDuplicateContext(expr->else_expression());
1517d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // If control flow falls through Visit, merge it with true case here.
15180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!context()->IsTest()) {
1519d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&done);
1520d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1521d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1522d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1523d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1524d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitLiteral(Literal* expr) {
1525d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ Literal");
1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(expr->value());
1527d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1528d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1529d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1530f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1531f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ FunctionLiteral");
1532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Build the function boilerplate and instantiate it.
1534f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<SharedFunctionInfo> function_info =
1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Compiler::BuildFunctionInfo(expr, script(), info_);
1536f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (function_info.is_null()) {
1537f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    SetStackOverflow();
1538f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    return;
1539f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
15408a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  EmitNewClosure(function_info, expr->pretenure());
1541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1542f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1543f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(arv): Implement
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ ClassLiteral");
1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->extends() != NULL) {
1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitForEffect(expr->extends());
1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  context()->Plug(isolate()->factory()->undefined_value());
1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitNativeFunctionLiteral(
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    NativeFunctionLiteral* expr) {
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Comment cmnt(masm_, "[ NativeFunctionLiteral");
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Compute the function template for the native function.
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> name = expr->name();
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Handle<v8::FunctionTemplate> fun_template =
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      expr->extension()->GetNativeFunctionTemplate(
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          reinterpret_cast<v8::Isolate*>(isolate()), v8::Utils::ToLocal(name));
1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(!fun_template.IsEmpty());
1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Instantiate the function and create a shared function info from it.
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<JSFunction> fun = Utils::OpenHandle(*fun_template->GetFunction());
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const int literals = fun->NumberOfLiterals();
1568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = Handle<Code>(fun->shared()->code());
1569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
1570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<SharedFunctionInfo> shared =
1571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      isolate()->factory()->NewSharedFunctionInfo(
1572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          name, literals, FunctionKind::kNormalFunction, code,
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Handle<ScopeInfo>(fun->shared()->scope_info()),
1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          Handle<TypeFeedbackVector>(fun->shared()->feedback_vector()));
1575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shared->set_construct_stub(*construct_stub);
1576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Copy the function data to the shared function info.
1578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shared->set_function_data(fun->shared()->function_data());
1579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int parameters = fun->shared()->formal_parameter_count();
1580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  shared->set_formal_parameter_count(parameters);
1581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  EmitNewClosure(shared, false);
1583f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1584f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1586d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThrow(Throw* expr) {
1587d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ Throw");
15880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->exception());
1589d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ CallRuntime(Runtime::kThrow, 1);
1590d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Never returns here.
1591d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1592d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1593d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
159469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochFullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit(
159569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* stack_depth,
159669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int* context_length) {
1597d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The macros used here must preserve the result register.
159869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ Drop(*stack_depth);
1599d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ PopTryHandler();
160069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  *stack_depth = 0;
160169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return previous_;
1602d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1603d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
160480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) {
16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Expression* sub_expr;
16073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Handle<String> check;
16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitLiteralCompareTypeof(expr, sub_expr, check);
16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return true;
16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitLiteralCompareNil(expr, sub_expr, kUndefinedValue);
16153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return true;
16163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
16173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (expr->IsLiteralCompareNull(&sub_expr)) {
16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EmitLiteralCompareNil(expr, sub_expr, kNullValue);
16203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return true;
16213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
16223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return false;
16243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
16253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
16263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::Patch(Isolate* isolate, Code* unoptimized) {
1628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
1629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement);
1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Increment loop nesting level by one and iterate over the back edge table
1632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to find the matching loops to patch the interrupt
1633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // call to an unconditional call to the replacement code.
1634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level() + 1;
1635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (loop_nesting_level > Code::kMaxLoopNestingMarker) return;
1636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BackEdgeTable back_edges(unoptimized, &no_gc);
1638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (uint32_t i = 0; i < back_edges.length(); i++) {
1639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (static_cast<int>(back_edges.loop_depth(i)) == loop_nesting_level) {
1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK_EQ(INTERRUPT, GetBackEdgeState(isolate,
1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            unoptimized,
1642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            back_edges.pc(i)));
1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PatchAt(unoptimized, back_edges.pc(i), ON_STACK_REPLACEMENT, patch);
1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unoptimized->set_allow_osr_at_loop_nesting_level(loop_nesting_level);
1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Verify(isolate, unoptimized));
1649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::Revert(Isolate* isolate, Code* unoptimized) {
1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Code* patch = isolate->builtins()->builtin(Builtins::kInterruptCheck);
1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Iterate over the back edge table and revert the patched interrupt calls.
1657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
1658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BackEdgeTable back_edges(unoptimized, &no_gc);
1660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (uint32_t i = 0; i < back_edges.length(); i++) {
1661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (static_cast<int>(back_edges.loop_depth(i)) <= loop_nesting_level) {
1662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK_NE(INTERRUPT, GetBackEdgeState(isolate,
1663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            unoptimized,
1664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            back_edges.pc(i)));
1665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PatchAt(unoptimized, back_edges.pc(i), INTERRUPT, patch);
1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unoptimized->set_allow_osr_at_loop_nesting_level(0);
1670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assert that none of the back edges are patched anymore.
1671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Verify(isolate, unoptimized));
1672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::AddStackCheck(Handle<Code> code, uint32_t pc_offset) {
1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
1677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = code->GetIsolate();
1678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address pc = code->instruction_start() + pc_offset;
1679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Code* patch = isolate->builtins()->builtin(Builtins::kOsrAfterStackCheck);
1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PatchAt(*code, pc, OSR_AFTER_STACK_CHECK, patch);
1681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::RemoveStackCheck(Handle<Code> code, uint32_t pc_offset) {
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = code->GetIsolate();
1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address pc = code->instruction_start() + pc_offset;
1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (OSR_AFTER_STACK_CHECK == GetBackEdgeState(isolate, *code, pc)) {
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Code* patch = isolate->builtins()->builtin(Builtins::kOnStackReplacement);
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PatchAt(*code, pc, ON_STACK_REPLACEMENT, patch);
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool BackEdgeTable::Verify(Isolate* isolate, Code* unoptimized) {
1698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int loop_nesting_level = unoptimized->allow_osr_at_loop_nesting_level();
1700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  BackEdgeTable back_edges(unoptimized, &no_gc);
1701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (uint32_t i = 0; i < back_edges.length(); i++) {
1702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t loop_depth = back_edges.loop_depth(i);
1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_LE(static_cast<int>(loop_depth), Code::kMaxLoopNestingMarker);
1704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Assert that all back edges for shallower loops (and only those)
1705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // have already been patched.
1706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ((static_cast<int>(loop_depth) <= loop_nesting_level),
1707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             GetBackEdgeState(isolate,
1708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              unoptimized,
1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              back_edges.pc(i)) != INTERRUPT);
1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // DEBUG
1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1716d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#undef __
1717d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1718d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1719d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} }  // namespace v8::internal
1720