full-codegen.cc revision 44f0eee88ff00398ff7f715fab053374d808c90d
1b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Copyright 2010 the V8 project authors. All rights reserved.
2d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Redistribution and use in source and binary forms, with or without
3d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// modification, are permitted provided that the following conditions are
4d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// met:
5d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//
6d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//     * Redistributions of source code must retain the above copyright
7d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       notice, this list of conditions and the following disclaimer.
8d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//     * Redistributions in binary form must reproduce the above
9d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       copyright notice, this list of conditions and the following
10d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       disclaimer in the documentation and/or other materials provided
11d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       with the distribution.
12d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//     * Neither the name of Google Inc. nor the names of its
13d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       contributors may be used to endorse or promote products derived
14d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       from this software without specific prior written permission.
15d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//
16d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
28d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "v8.h"
29d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
30d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "codegen-inl.h"
31d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "compiler.h"
32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "debug.h"
33d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "full-codegen.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "liveedit.h"
3580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen#include "macro-assembler.h"
36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "prettyprinter.h"
376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "scopes.h"
38d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "stub-cache.h"
39d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
40d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkenamespace v8 {
41d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkenamespace internal {
42d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::Check(Statement* stmt) {
447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt);
457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::Check(Expression* expr) {
497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr);
507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitDeclaration(Declaration* decl) {
547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitBlock(Block* stmt) {
587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitExpressionStatement(
627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ExpressionStatement* stmt) {
637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Check if expression is breakable.
647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->expression());
657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) {
697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) {
737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // If the condition is breakable the if statement is breakable.
747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->condition());
757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitContinueStatement(
797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ContinueStatement* stmt) {
807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Return is breakable if the expression is.
897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->expression());
907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitWithEnterStatement(
947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    WithEnterStatement* stmt) {
957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->expression());
967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitWithExitStatement(
1007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    WithExitStatement* stmt) {
1017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
1057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Switch statements breakable if the tag expression is.
1067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->tag());
1077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
1117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark do while as breakable to avoid adding a break slot in front of it.
1127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
1137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) {
1177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark while statements breakable if the condition expression is.
1187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->cond());
1197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1217f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitForStatement(ForStatement* stmt) {
1237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark for statements breakable if the condition expression is.
1247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (stmt->cond() != NULL) {
1257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    Visit(stmt->cond());
1267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
1277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) {
1317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark for in statements breakable if the enumerable expression is.
1327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(stmt->enumerable());
1337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitTryCatchStatement(
1377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    TryCatchStatement* stmt) {
1387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark try catch as breakable to avoid adding a break slot in front of it.
1397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
1407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitTryFinallyStatement(
1447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    TryFinallyStatement* stmt) {
1457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Mark try finally as breakable to avoid adding a break slot in front of it.
1467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
1477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitDebuggerStatement(
1517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    DebuggerStatement* stmt) {
1527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // The debugger statement is breakable.
1537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
1547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
1587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitSharedFunctionInfoLiteral(
1627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    SharedFunctionInfoLiteral* expr) {
1637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitConditional(Conditional* expr) {
1677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) {
1717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitLiteral(Literal* expr) {
1757f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
1797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) {
1837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
1877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitCatchExtensionObject(
1917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CatchExtensionObject* expr) {
1927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitAssignment(Assignment* expr) {
1967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // If assigning to a property (including a global property) the assignment is
1977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // breakable.
1987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Variable* var = expr->target()->AsVariableProxy()->AsVariable();
1997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Property* prop = expr->target()->AsProperty();
2007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (prop != NULL || (var != NULL && var->is_global())) {
2017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    is_breakable_ = true;
2027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    return;
2037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
2047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Otherwise the assignment is breakable if the assigned value is.
2067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->value());
2077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitThrow(Throw* expr) {
2117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Throw is breakable if the expression is.
2127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->exception());
2137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
21680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid BreakableStatementChecker::VisitIncrementOperation(
21780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    IncrementOperation* expr) {
21880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  UNREACHABLE();
21980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
22080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
22180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitProperty(Property* expr) {
2237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Property load is breakable.
2247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
2257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitCall(Call* expr) {
2297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Function calls both through IC and call stub are breakable.
2307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
2317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitCallNew(CallNew* expr) {
2357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Function calls through new are breakable.
2367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  is_breakable_ = true;
2377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) {
2417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) {
2457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->expression());
2467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
2507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->expression());
2517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
2557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->left());
2567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->right());
2577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
26080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid BreakableStatementChecker::VisitCompareToNull(CompareToNull* expr) {
26180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Visit(expr->expression());
26280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
26380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
26480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
2667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->left());
2677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  Visit(expr->right());
2687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
2727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
2737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
2747f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
275d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#define __ ACCESS_MASM(masm())
276d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
277f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochbool FullCodeGenerator::MakeCode(CompilationInfo* info) {
27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = info->isolate();
2793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  Handle<Script> script = info->script();
280d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (!script->IsUndefined() && !script->source()->IsUndefined()) {
281d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    int len = String::cast(script->source())->length();
28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate->counters()->total_full_codegen_source_size()->Increment(len);
283d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_codegen) {
285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("Full Compiler - ");
286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
2873100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  CodeGenerator::MakeCodePrologue(info);
288d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const int kInitialBufferSize = 4 * KB;
289d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  MacroAssembler masm(NULL, kInitialBufferSize);
290b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#ifdef ENABLE_GDB_JIT_INTERFACE
291b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  masm.positions_recorder()->StartGDBJITLineInfoRecording();
292b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif
293402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
2943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu  FullCodeGenerator cgen(&masm);
295756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  cgen.Generate(info);
296d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (cgen.HasStackOverflow()) {
29744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    ASSERT(!isolate->has_pending_exception());
298f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    return false;
299d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned table_offset = cgen.EmitStackCheckTable();
301f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
302d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
303f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  code->set_optimizable(info->IsOptimizable());
305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  cgen.PopulateDeoptimizationData(code);
306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  code->set_allow_osr_at_loop_nesting_level(0);
3081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  code->set_stack_check_table_offset(table_offset);
309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CodeGenerator::PrintCode(code, info);
310f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  info->SetCode(code);  // may be an empty handle.
311b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#ifdef ENABLE_GDB_JIT_INTERFACE
3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (FLAG_gdbjit && !code.is_null()) {
313b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    GDBJITLineInfo* lineinfo =
314b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        masm.positions_recorder()->DetachGDBJITLineInfo();
315b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
316b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    GDBJIT(RegisterDetailedLineInfo(*code, lineinfo));
317b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
318b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif
319f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  return !code.is_null();
320d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
321d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
322d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochunsigned FullCodeGenerator::EmitStackCheckTable() {
324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The stack check table consists of a length (in number of entries)
325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // field, and then a sequence of entries.  Each entry is a pair of AST id
326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // and code-relative pc offset.
327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  masm()->Align(kIntSize);
328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  masm()->RecordComment("[ Stack check table");
329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned offset = masm()->pc_offset();
330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned length = stack_checks_.length();
331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ dd(length);
332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (unsigned i = 0; i < length; ++i) {
333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ dd(stack_checks_[i].id);
334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ dd(stack_checks_[i].pc_and_state);
335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  masm()->RecordComment("]");
337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return offset;
338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Fill in the deoptimization information.
343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!info_->HasDeoptimizationSupport()) return;
345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = bailout_entries_.length();
346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Handle<DeoptimizationOutputData> data =
34744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate()->factory()->
34844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      NewDeoptimizationOutputData(length, TENURED);
349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; i++) {
350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    data->SetAstId(i, Smi::FromInt(bailout_entries_[i].id));
351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  code->set_deoptimization_data(*data);
354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::PrepareForBailout(AstNode* node, State state) {
358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(node->id(), state);
359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::RecordJSReturnSite(Call* call) {
363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We record the offset of the function return so we can rebuild the frame
364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // if the function was inlined, i.e., this is the return address in the
365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // inlined function's frame.
366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  //
367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The state is ignored.  We defensively set it to TOS_REG, which is the
368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // real state of the unoptimized code at the return site.
369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(call->ReturnId(), TOS_REG);
370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // In debug builds, mark the return so we can verify that this function
372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // was called.
373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!call->return_is_recorded_);
374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  call->return_is_recorded_ = true;
375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::PrepareForBailoutForId(int id, State state) {
380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // There's no need to prepare this code for bailouts from already optimized
381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // code or code that can't be optimized.
382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!FLAG_deopt || !info_->HasDeoptimizationSupport()) return;
383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned pc_and_state =
384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      StateField::encode(state) | PcField::encode(masm_->pc_offset());
385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BailoutEntry entry = { id, pc_and_state };
386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Assert that we don't have multiple bailout entries for the same node.
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < bailout_entries_.length(); i++) {
389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (bailout_entries_.at(i).id == entry.id) {
390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      AstPrinter printer;
391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintF("%s", printer.PrintProgram(info_->function()));
392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNREACHABLE();
393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif  // DEBUG
396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bailout_entries_.Add(entry);
397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::RecordStackCheck(int ast_id) {
401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The pc offset does not need to be encoded and packed together with a
402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // state.
403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  BailoutEntry entry = { ast_id, masm_->pc_offset() };
404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  stack_checks_.Add(entry);
405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
408d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeint FullCodeGenerator::SlotOffset(Slot* slot) {
409d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(slot != NULL);
410d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Offset is negative because higher indexes are at lower addresses.
411d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int offset = -slot->index() * kPointerSize;
412d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Adjust by a (parameter or local) base offset.
413d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  switch (slot->type()) {
414d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Slot::PARAMETER:
4153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu      offset += (scope()->num_parameters() + 1) * kPointerSize;
416d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
417d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Slot::LOCAL:
418d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      offset += JavaScriptFrameConstants::kLocal0Offset;
419d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      break;
420d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Slot::CONTEXT:
421d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    case Slot::LOOKUP:
422d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      UNREACHABLE();
423d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
424d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return offset;
425d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
426d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
427d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
42880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenbool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
42980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Inline smi case inside loops, but not division and modulo which
43080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // are too complicated and take up too much space.
4310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (op == Token::DIV ||op == Token::MOD) return false;
4320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (FLAG_always_inline_smi_code) return true;
4330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return loop_depth_ > 0;
43480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
43580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
43680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4370d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Register reg) const {
4380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4410d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
4420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
4430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4460d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Register reg) const {
4470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(reg);
4480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4510d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Register reg) const {
4520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
4530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Move(result_register(), reg);
454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
4550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->DoTest(true_label_, false_label_, fall_through_);
4560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4590d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::PlugTOS() const {
4600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(1);
4610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4640d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
4650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ pop(result_register());
4660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4690d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::PlugTOS() const {
4700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4730d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::PlugTOS() const {
4740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // For simplicity we always test the accumulator register.
4750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ pop(result_register());
476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
4770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->DoTest(true_label_, false_label_, fall_through_);
4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4810d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::PrepareTest(
4820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
4830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false,
4840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_true,
4850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_false,
4860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** fall_through) const {
4870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // In an effect context, the true and the false case branch to the
4880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // same label.
4890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_true = *if_false = *fall_through = materialize_true;
4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
4910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
4930d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::PrepareTest(
4940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
4950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false,
4960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_true,
4970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_false,
4980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** fall_through) const {
4990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_true = *fall_through = materialize_true;
5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_false = materialize_false;
5010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::PrepareTest(
5050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
5060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false,
5070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_true,
5080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_false,
5090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** fall_through) const {
5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_true = *fall_through = materialize_true;
5110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_false = materialize_false;
5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5150d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::PrepareTest(
5160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_true,
5170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* materialize_false,
5180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_true,
5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** if_false,
5200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label** fall_through) const {
5210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_true = true_label_;
5220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *if_false = false_label_;
5230d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  *fall_through = fall_through_;
52480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
52580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
52680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
527d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitDeclarations(
528d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ZoneList<Declaration*>* declarations) {
529d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int length = declarations->length();
530d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int globals = 0;
531d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (int i = 0; i < length; i++) {
532d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Declaration* decl = declarations->at(i);
533d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Variable* var = decl->proxy()->var();
5340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* slot = var->AsSlot();
535d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
536d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // If it was not possible to allocate the variable at compile
537d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // time, we need to "declare" it at runtime to make sure it
538d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // actually exists in the local context.
539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) {
540d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      VisitDeclaration(decl);
541d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } else {
542d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      // Count global variables and functions for later processing
543d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      globals++;
544d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
545d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
546d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
547d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Compute array of global variable and function declarations.
548d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Do nothing in case of no declared global functions or variables.
549d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (globals > 0) {
55044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<FixedArray> array =
55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate()->factory()->NewFixedArray(2 * globals, TENURED);
552d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    for (int j = 0, i = 0; i < length; i++) {
553d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Declaration* decl = declarations->at(i);
554d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Variable* var = decl->proxy()->var();
5550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      Slot* slot = var->AsSlot();
556d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
557d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      if ((slot == NULL || slot->type() != Slot::LOOKUP) && var->is_global()) {
558d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        array->set(j++, *(var->name()));
559d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        if (decl->fun() == NULL) {
560d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke          if (var->mode() == Variable::CONST) {
561d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke            // In case this is const property use the hole.
562d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke            array->set_the_hole(j++);
563d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke          } else {
564d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke            array->set_undefined(j++);
565d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke          }
566d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        } else {
5676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block          Handle<SharedFunctionInfo> function =
568f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch              Compiler::BuildFunctionInfo(decl->fun(), script());
569d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke          // Check for stack-overflow exception.
570f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch          if (function.is_null()) {
571f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch            SetStackOverflow();
572f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch            return;
573f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch          }
574d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke          array->set(j++, *function);
575d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke        }
576d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      }
577d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
578d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Invoke the platform-dependent code generator to do the actual
579d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // declaration the global variables and functions.
580d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    DeclareGlobals(array);
581d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
582d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
583d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
584d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
585d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
586d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_debug_info) {
587d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CodeGenerator::RecordPositions(masm_, fun->start_position());
588d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
589d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
590d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
591d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
592d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
593d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_debug_info) {
594bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
595d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
596d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
597d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
598d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
599d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::SetStatementPosition(Statement* stmt) {
600d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_debug_info) {
6017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#ifdef ENABLE_DEBUGGER_SUPPORT
60244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!isolate()->debugger()->IsDebuggerActive()) {
6037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
6047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
6057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Check if the statement will be breakable without adding a debug break
6067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // slot.
6077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      BreakableStatementChecker checker;
6087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      checker.Check(stmt);
6097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Record the statement position right here if the statement is not
6107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // breakable. For breakable statements the actual recording of the
6117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // position will be postponed to the breakable code (typically an IC).
6127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      bool position_recorded = CodeGenerator::RecordPositions(
6137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          masm_, stmt->statement_pos(), !checker.is_breakable());
6147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // If the position recording did record a new position generate a debug
6157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // break slot to make the statement breakable.
6167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      if (position_recorded) {
6177f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        Debug::GenerateSlot(masm_);
6187f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      }
6197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
6207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#else
621d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
6227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#endif
6237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
6247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
6257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
6267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
6277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) {
6287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  if (FLAG_debug_info) {
6297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#ifdef ENABLE_DEBUGGER_SUPPORT
63044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!isolate()->debugger()->IsDebuggerActive()) {
6317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      CodeGenerator::RecordPositions(masm_, pos);
6327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    } else {
6337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Check if the expression will be breakable without adding a debug break
6347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // slot.
6357f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      BreakableStatementChecker checker;
6367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      checker.Check(expr);
6377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // Record a statement position right here if the expression is not
6387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // breakable. For breakable expressions the actual recording of the
6397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // position will be postponed to the breakable code (typically an IC).
6407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // NOTE this will record a statement position for something which might
6417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // not be a statement. As stepping in the debugger will only stop at
6427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // statement positions this is used for e.g. the condition expression of
6437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // a do while loop.
6447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      bool position_recorded = CodeGenerator::RecordPositions(
6457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch          masm_, pos, !checker.is_breakable());
6467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // If the position recording did record a new position generate a debug
6477f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      // break slot to make the statement breakable.
6487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      if (position_recorded) {
6497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch        Debug::GenerateSlot(masm_);
6507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch      }
6517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    }
6527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#else
6537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CodeGenerator::RecordPositions(masm_, pos);
6547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#endif
655d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
656d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
657d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
658d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
659d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::SetStatementPosition(int pos) {
660d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_debug_info) {
661d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CodeGenerator::RecordPositions(masm_, pos);
662d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
663d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
664d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
665d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::SetSourcePosition(int pos) {
667d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (FLAG_debug_info && pos != RelocInfo::kNoPosition) {
668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    masm_->positions_recorder()->RecordPosition(pos);
669d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
670d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
671d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
6730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen// Lookup table for code generators for  special runtime calls which are
6740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen// generated inline.
6750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)          \
6760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    &FullCodeGenerator::Emit##Name,
677791712a13f1814dd3ab5d1a5ab8ff5dbc476f6d6Steve Block
6780d5e116f6aee03185f237311a943491bb079a768Kristian Monsenconst FullCodeGenerator::InlineFunctionGenerator
6790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  FullCodeGenerator::kInlineFunctionGenerators[] = {
6800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
6810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
6820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  };
6830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen#undef INLINE_FUNCTION_GENERATOR_ADDRESS
6840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6860d5e116f6aee03185f237311a943491bb079a768Kristian MonsenFullCodeGenerator::InlineFunctionGenerator
6870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int lookup_index =
689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction);
690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(lookup_index >= 0);
691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(static_cast<size_t>(lookup_index) <
692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           ARRAY_SIZE(kInlineFunctionGenerators));
693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return kInlineFunctionGenerators[lookup_index];
6940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
6950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
6970d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) {
6980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ZoneList<Expression*>* args = node->arguments();
6990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Handle<String> name = node->name();
70044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  const Runtime::Function* function = node->function();
7010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(function != NULL);
7020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(function->intrinsic_type == Runtime::INLINE);
7030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  InlineFunctionGenerator generator =
7040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen      FindInlineFunctionGenerator(function->function_id);
7050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ((*this).*(generator))(args);
70680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
70780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
70880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
70980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
71080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Comment cmnt(masm_, "[ BinaryOperation");
71180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Token::Value op = expr->op();
71280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Expression* left = expr->left();
71380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Expression* right = expr->right();
71480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
71580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  OverwriteMode mode = NO_OVERWRITE;
71680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (left->ResultOverwriteAllowed()) {
71780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    mode = OVERWRITE_LEFT;
71880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else if (right->ResultOverwriteAllowed()) {
71980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    mode = OVERWRITE_RIGHT;
72080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
72180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
72280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  switch (op) {
72380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::COMMA:
72480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      VisitForEffect(left);
725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (context()->IsTest()) ForwardBailoutToChild(expr);
726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      context()->HandleExpression(right);
72780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
72880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
72980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::OR:
73080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::AND:
73180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      EmitLogicalOperation(expr);
73280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
73380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
73480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::ADD:
73580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SUB:
73680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::DIV:
73780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::MOD:
73880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::MUL:
73980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_OR:
74080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_AND:
74180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::BIT_XOR:
74280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHL:
74380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SHR:
74480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    case Token::SAR: {
745e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Load both operands.
746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VisitForStackValue(left);
747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      VisitForAccumulatorValue(right);
74880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
74980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      SetSourcePosition(expr->position());
75080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      if (ShouldInlineSmiCase(op)) {
751e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        EmitInlineSmiBinaryOp(expr, op, mode, left, right);
75280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      } else {
7530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen        EmitBinaryOp(op, mode);
75480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      }
75580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      break;
75680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
75780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
75880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    default:
75980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen      UNREACHABLE();
76080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
7617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
7627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
7637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
764d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
765d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label eval_right, done;
766d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
7670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->EmitLogicalLeft(expr, &eval_right, &done);
768d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->RightId(), NO_REGISTERS);
770d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&eval_right);
771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (context()->IsTest()) ForwardBailoutToChild(expr);
772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->HandleExpression(expr->right());
773d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
774d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
775d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
776d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
777d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
7780d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::EmitLogicalLeft(BinaryOperation* expr,
7790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Label* eval_right,
7800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                       Label* done) const {
7810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (expr->op() == Token::OR) {
7820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->VisitForControl(expr->left(), done, eval_right, eval_right);
7830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
7840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ASSERT(expr->op() == Token::AND);
7850d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->VisitForControl(expr->left(), eval_right, done, eval_right);
7860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
7870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
7880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
7900d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::EmitLogicalLeft(
7910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    BinaryOperation* expr,
7920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* eval_right,
7930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* done) const {
794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HandleExpression(expr->left());
7950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // We want the value in the accumulator for the test, and on the stack in case
7960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // we need it.
79780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ push(result_register());
7980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Label discard, restore;
7990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (expr->op() == Token::OR) {
800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
8010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->DoTest(&restore, &discard, &restore);
8020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
8030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ASSERT(expr->op() == Token::AND);
804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
8050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->DoTest(&discard, &restore, &restore);
8060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
8070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&restore);
8080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ pop(result_register());
8090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ jmp(done);
8100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ bind(&discard);
8110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ Drop(1);
8120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
8130d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
81480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
8150d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::EmitLogicalLeft(
8160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    BinaryOperation* expr,
8170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* eval_right,
8180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Label* done) const {
8190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  codegen()->VisitForAccumulatorValue(expr->left());
8200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // We want the value in the accumulator for the test, and on the stack in case
8210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  // we need it.
8220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  __ push(result_register());
82380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Label discard;
8240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (expr->op() == Token::OR) {
825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
8260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->DoTest(done, &discard, &discard);
8270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
8280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ASSERT(expr->op() == Token::AND);
829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
8300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->DoTest(&discard, done, &discard);
83180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
83280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ bind(&discard);
83380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  __ Drop(1);
83480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
83580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
83680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
8370d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::EmitLogicalLeft(BinaryOperation* expr,
8380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                     Label* eval_right,
8390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                                                     Label* done) const {
8400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (expr->op() == Token::OR) {
8410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->VisitForControl(expr->left(),
8420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                               true_label_, eval_right, eval_right);
8430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  } else {
8440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ASSERT(expr->op() == Token::AND);
8450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    codegen()->VisitForControl(expr->left(),
8460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen                               eval_right, false_label_, eval_right);
8470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
8480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
8490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
8500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::ForwardBailoutToChild(Expression* expr) {
852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!info_->HasDeoptimizationSupport()) return;
853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(context()->IsTest());
854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(expr == forward_bailout_stack_->expr());
855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  forward_bailout_pending_ = forward_bailout_stack_;
856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::EffectContext::HandleExpression(
860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Expression* expr) const {
861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  codegen()->HandleInNonTestContext(expr, NO_REGISTERS);
862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::AccumulatorValueContext::HandleExpression(
866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Expression* expr) const {
867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  codegen()->HandleInNonTestContext(expr, TOS_REG);
868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::StackValueContext::HandleExpression(
872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Expression* expr) const {
873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  codegen()->HandleInNonTestContext(expr, NO_REGISTERS);
874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::TestContext::HandleExpression(Expression* expr) const {
878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  codegen()->VisitInTestContext(expr);
879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::HandleInNonTestContext(Expression* expr, State state) {
883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(forward_bailout_pending_ == NULL);
884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AstVisitor::Visit(expr);
885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailout(expr, state);
886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Forwarding bailouts to children is a one shot operation. It
887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // should have been processed at this point.
888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(forward_bailout_pending_ == NULL);
889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FullCodeGenerator::VisitInTestContext(Expression* expr) {
893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ForwardBailoutStack stack(expr, forward_bailout_pending_);
894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ForwardBailoutStack* saved = forward_bailout_stack_;
895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  forward_bailout_pending_ = NULL;
896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  forward_bailout_stack_ = &stack;
897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AstVisitor::Visit(expr);
898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  forward_bailout_stack_ = saved;
899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
902d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBlock(Block* stmt) {
903d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ Block");
904d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Breakable nested_statement(this, stmt);
905d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
9071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
908d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  VisitStatements(stmt->statements());
909d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(nested_statement.break_target());
910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
911d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
912d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
913d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
914d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
915d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ ExpressionStatement");
916d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
917d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  VisitForEffect(stmt->expression());
918d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
919d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
920d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
921d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
922d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ EmptyStatement");
923d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
924d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
925d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
926d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
927d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
928d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ IfStatement");
929d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
930d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label then_part, else_part, done;
931d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
93280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (stmt->HasElseStatement()) {
93380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
93580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ bind(&then_part);
93680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Visit(stmt->then_statement());
93780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ jmp(&done);
938d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
94080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ bind(&else_part);
94180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Visit(stmt->else_statement());
94280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
94380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    VisitForControl(stmt->condition(), &then_part, &done, &then_part);
944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
94580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ bind(&then_part);
94680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    Visit(stmt->then_statement());
947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
94980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
950d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->id(), NO_REGISTERS);
952d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
953d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
954d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
955d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
956d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_,  "[ ContinueStatement");
957d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
958d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  NestedStatement* current = nesting_stack_;
959d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int stack_depth = 0;
960db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // When continuing, we clobber the unpredictable value in the accumulator
961db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // with one that's safe for GC.  If we hit an exit from the try block of
962db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // try...finally on our way out, we will unconditionally preserve the
963db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // accumulator on the stack.
964db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  ClearAccumulator();
965d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  while (!current->IsContinueTarget(stmt->target())) {
966d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    stack_depth = current->Exit(stack_depth);
967d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    current = current->outer();
968d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
969d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Drop(stack_depth);
970d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
971d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Iteration* loop = current->AsIteration();
972d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ jmp(loop->continue_target());
973d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
974d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
975d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
976d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
977d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_,  "[ BreakStatement");
978d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
979d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  NestedStatement* current = nesting_stack_;
980d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int stack_depth = 0;
981db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // When breaking, we clobber the unpredictable value in the accumulator
982db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // with one that's safe for GC.  If we hit an exit from the try block of
983db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // try...finally on our way out, we will unconditionally preserve the
984db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // accumulator on the stack.
985db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  ClearAccumulator();
986d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  while (!current->IsBreakTarget(stmt->target())) {
987d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    stack_depth = current->Exit(stack_depth);
988d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    current = current->outer();
989d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
990d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Drop(stack_depth);
991d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
992d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Breakable* target = current->AsBreakable();
993d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ jmp(target->break_target());
994d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
995d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
996d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
997d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
998d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ ReturnStatement");
999d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1000d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Expression* expr = stmt->expression();
10010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForAccumulatorValue(expr);
1002d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1003d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Exit all nested statements.
1004d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  NestedStatement* current = nesting_stack_;
1005d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int stack_depth = 0;
1006d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  while (current != NULL) {
1007d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    stack_depth = current->Exit(stack_depth);
1008d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    current = current->outer();
1009d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1010d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Drop(stack_depth);
1011d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
10127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  EmitReturnSequence();
1013d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1014d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1015d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1016d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
1017d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ WithEnterStatement");
1018d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1019d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
10200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(stmt->expression());
1021d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (stmt->is_catch_block()) {
1022d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kPushCatchContext, 1);
1023d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else {
1024d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kPushContext, 1);
1025d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1026d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Both runtime calls return the new context in both the context and the
1027d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // result registers.
1028d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1029d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Update local stack frame context field.
1030d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1031d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1032d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1033d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1034d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) {
1035d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ WithExitStatement");
1036d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1037d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1038d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Pop context.
1039d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1040d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Update local stack frame context field.
1041d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1042d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1043d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1044d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1045d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
1046d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ DoWhileStatement");
1047d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label body, stack_check;
1049d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1050d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Iteration loop_statement(this, stmt);
1051d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  increment_loop_depth();
1052d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1053d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&body);
1054d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Visit(stmt->body());
1055d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
105680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Record the position of the do while condition and make sure it is
105780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // possible to break on the condition.
1058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(loop_statement.continue_target());
1059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
10607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetExpressionPosition(stmt->cond(), stmt->condition_position());
106180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VisitForControl(stmt->cond(),
1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                  &stack_check,
106380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                  loop_statement.break_target(),
1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                  &stack_check);
10657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Check stack before looping.
1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&stack_check);
1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EmitStackCheck(stmt);
1070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ jmp(&body);
1071d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(loop_statement.break_target());
1074d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  decrement_loop_depth();
1075d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1076d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1077d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1078d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1079d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ WhileStatement");
1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label test, body;
1081d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1082d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Iteration loop_statement(this, stmt);
1083d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  increment_loop_depth();
1084d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1085d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Emit the test at the bottom of the loop.
1086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ jmp(&test);
1087d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1089d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&body);
1090d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Visit(stmt->body());
109180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
109280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Emit the statement position here as this is where the while
109380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // statement code starts.
1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(loop_statement.continue_target());
10957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetStatementPosition(stmt);
1096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1097d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check stack before looping.
1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EmitStackCheck(stmt);
1099d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&test);
110180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VisitForControl(stmt->cond(),
110280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                  &body,
110380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                  loop_statement.break_target(),
110480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                  loop_statement.break_target());
1105d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1107d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(loop_statement.break_target());
1108d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  decrement_loop_depth();
1109d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1110d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1111d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1112d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
1113d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ ForStatement");
1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label test, body;
1115d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Iteration loop_statement(this, stmt);
1117d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (stmt->init() != NULL) {
1118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Visit(stmt->init());
1119d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1120d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  increment_loop_depth();
1122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Emit the test at the bottom of the loop (even if empty).
1123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ jmp(&test);
1124d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1126d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&body);
1127d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Visit(stmt->body());
1128d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
1130d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(loop_statement.continue_target());
1131d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1132d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (stmt->next() != NULL) {
1133d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Visit(stmt->next());
1134d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1135d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
113680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Emit the statement position here as this is where the for
113780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // statement code starts.
11387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetStatementPosition(stmt);
1139d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1140d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Check stack before looping.
1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  EmitStackCheck(stmt);
1142d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&test);
1144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (stmt->cond() != NULL) {
114580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    VisitForControl(stmt->cond(),
114680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    &body,
114780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    loop_statement.break_target(),
114880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                    loop_statement.break_target());
1149d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } else {
1150d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ jmp(&body);
1151d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1152d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1154d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(loop_statement.break_target());
1155d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  decrement_loop_depth();
1156d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1158d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1159d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1160d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ TryCatchStatement");
1161d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1162d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The try block adds a handler to the exception handler chain
1163d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // before entering, and removes it again when exiting normally.
1164d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // If an exception is thrown during execution of the try block,
1165d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // control is passed to the handler, which also consumes the handler.
1166d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // At this point, the exception is in a register, and store it in
1167d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // the temporary local variable (prints as ".catch-var") before
1168d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // executing the catch block. The catch block has been rewritten
1169d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // to introduce a new scope to bind the catch variable and to remove
1170d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // that scope again afterwards.
1171d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1172d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label try_handler_setup, catch_entry, done;
1173d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Call(&try_handler_setup);
1174d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Try handler code, exception in result register.
1175d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1176d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Store exception in local .catch variable before executing catch block.
1177d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {
1178d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // The catch variable is *always* a variable proxy for a local variable.
1179d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Variable* catch_var = stmt->catch_var()->AsVariableProxy()->AsVariable();
1180d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT_NOT_NULL(catch_var);
11810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    Slot* variable_slot = catch_var->AsSlot();
1182d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT_NOT_NULL(variable_slot);
1183d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ASSERT_EQ(Slot::LOCAL, variable_slot->type());
1184d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    StoreToFrameField(SlotOffset(variable_slot), result_register());
1185d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1186d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1187d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Visit(stmt->catch_block());
1188d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ jmp(&done);
1189d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1190d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Try block code. Sets up the exception handler chain.
1191d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&try_handler_setup);
1192d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {
1193d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    TryCatch try_block(this, &catch_entry);
1194d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
1195d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Visit(stmt->try_block());
1196d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ PopTryHandler();
1197d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1198d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&done);
1199d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1200d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1201d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1202d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1203d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ TryFinallyStatement");
1204d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
1205d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Try finally is compiled by setting up a try-handler on the stack while
1206d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // executing the try body, and removing it again afterwards.
1207d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //
1208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The try-finally construct can enter the finally block in three ways:
1209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // 1. By exiting the try-block normally. This removes the try-handler and
1210d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //      calls the finally block code before continuing.
1211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // 2. By exiting the try-block with a function-local control flow transfer
1212d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    (break/continue/return). The site of the, e.g., break removes the
1213d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    try handler and calls the finally block code before continuing
1214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    its outward control transfer.
1215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // 3. by exiting the try-block with a thrown exception.
1216d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    This can happen in nested function calls. It traverses the try-handler
1217d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    chain and consumes the try-handler entry before jumping to the
1218d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    handler code. The handler code then calls the finally-block before
1219d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    rethrowing the exception.
1220d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //
1221d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The finally block must assume a return address on top of the stack
1222d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // (or in the link register on ARM chips) and a value (return value or
1223d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // exception) in the result register (rax/eax/r0), both of which must
1224d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // be preserved. The return address isn't GC-safe, so it should be
1225d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // cooked before GC.
1226d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label finally_entry;
1227d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label try_handler_setup;
1228d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1229d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Setup the try-handler chain. Use a call to
1230d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Jump to try-handler setup and try-block code. Use call to put try-handler
1231d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // address on stack.
1232d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Call(&try_handler_setup);
1233d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Try handler code. Return address of call is pushed on handler stack.
1234d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {
1235d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // This code is only executed during stack-handler traversal when an
1236d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // exception is thrown. The execption is in the result register, which
1237d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // is retained by the finally block.
1238d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Call the finally block and then rethrow the exception.
1239d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ Call(&finally_entry);
1240d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ push(result_register());
1241d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ CallRuntime(Runtime::kReThrow, 1);
1242d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1243d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1244d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&finally_entry);
1245d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {
1246d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Finally block implementation.
1247d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Finally finally_block(this);
1248d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    EnterFinallyBlock();
1249d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Visit(stmt->finally_block());
1250d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    ExitFinallyBlock();  // Return to the calling code.
1251d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1252d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1253d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&try_handler_setup);
1254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  {
1255d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    // Setup try handler (stack pointer registers).
1256d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    TryFinally try_block(this, &finally_entry);
1257d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
1258d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Visit(stmt->try_block());
1259d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ PopTryHandler();
1260d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1261db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // Execute the finally block on the way out.  Clobber the unpredictable
1262db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // value in the accumulator with one that's safe for GC.  The finally
1263db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  // block will unconditionally preserve the accumulator on the stack.
1264db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch  ClearAccumulator();
1265d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Call(&finally_entry);
1266d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1267d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1268d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1269d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1270d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#ifdef ENABLE_DEBUGGER_SUPPORT
1271d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ DebuggerStatement");
1272d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SetStatementPosition(stmt);
12734515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
1274402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  __ DebugBreak();
1275d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Ignore the return value.
1276d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#endif
1277d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1278d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1279d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1280d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitConditional(Conditional* expr) {
1281d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ Conditional");
1282d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label true_case, false_case, done;
128380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
1284d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
1286d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&true_case);
12877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetExpressionPosition(expr->then_expression(),
12887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        expr->then_expression_position());
1289f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (context()->IsTest()) {
1290f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    const TestContext* for_test = TestContext::cast(context());
1291f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    VisitForControl(expr->then_expression(),
1292f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                    for_test->true_label(),
1293f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                    for_test->false_label(),
1294f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch                    NULL);
1295f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  } else {
1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context()->HandleExpression(expr->then_expression());
1297d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ jmp(&done);
1298d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1299d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
1301d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ bind(&false_case);
1302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (context()->IsTest()) ForwardBailoutToChild(expr);
13037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  SetExpressionPosition(expr->else_expression(),
13047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                        expr->else_expression_position());
1305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  context()->HandleExpression(expr->else_expression());
1306d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // If control flow falls through Visit, merge it with true case here.
13070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!context()->IsTest()) {
1308d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ bind(&done);
1309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1310d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1311d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1312d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitLiteral(Literal* expr) {
1314d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ Literal");
13150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(expr->handle());
1316d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1317d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1318d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ FunctionLiteral");
1321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Build the function boilerplate and instantiate it.
1323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Handle<SharedFunctionInfo> function_info =
1324f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch      Compiler::BuildFunctionInfo(expr, script());
1325f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  if (function_info.is_null()) {
1326f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    SetStackOverflow();
1327f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    return;
1328f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
13298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  EmitNewClosure(function_info, expr->pretenure());
1330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSharedFunctionInfoLiteral(
1334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    SharedFunctionInfoLiteral* expr) {
1335f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
13368a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  EmitNewClosure(expr->shared_function_info(), false);
1337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
1338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1339f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
1340d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
1341d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Call runtime routine to allocate the catch extension object and
1342d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // assign the exception value to the catch variable.
1343d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ CatchExtensionObject");
13440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->key());
13450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->value());
1346d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Create catch extension object.
1347d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
13480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  context()->Plug(result_register());
1349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1350d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1351d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThrow(Throw* expr) {
1353d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Comment cmnt(masm_, "[ Throw");
13540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  VisitForStackValue(expr->exception());
1355d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ CallRuntime(Runtime::kThrow, 1);
1356d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Never returns here.
1357d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1358d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1359d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
136080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::VisitIncrementOperation(IncrementOperation* expr) {
136180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  UNREACHABLE();
136280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
136380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
136480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1365d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeint FullCodeGenerator::TryFinally::Exit(int stack_depth) {
1366d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The macros used here must preserve the result register.
1367d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Drop(stack_depth);
1368d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ PopTryHandler();
1369d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Call(finally_entry_);
1370d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return 0;
1371d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1372d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1373d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1374d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeint FullCodeGenerator::TryCatch::Exit(int stack_depth) {
1375d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The macros used here must preserve the result register.
1376d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ Drop(stack_depth);
1377d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  __ PopTryHandler();
1378d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return 0;
1379d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1380d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
138180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1382d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#undef __
1383d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1384d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1385d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} }  // namespace v8::internal
1386