full-codegen.cc revision 3bec4d28b1f388dbc06a9c4276e1a03e86c52b04
1// Copyright 2009 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#include "v8.h" 29 30#include "codegen-inl.h" 31#include "compiler.h" 32#include "full-codegen.h" 33#include "scopes.h" 34#include "stub-cache.h" 35#include "debug.h" 36#include "liveedit.h" 37 38namespace v8 { 39namespace internal { 40 41#define BAILOUT(reason) \ 42 do { \ 43 if (FLAG_trace_bailout) { \ 44 PrintF("%s\n", reason); \ 45 } \ 46 has_supported_syntax_ = false; \ 47 return; \ 48 } while (false) 49 50 51#define CHECK_BAILOUT \ 52 do { \ 53 if (!has_supported_syntax_) return; \ 54 } while (false) 55 56 57void FullCodeGenSyntaxChecker::Check(FunctionLiteral* fun) { 58 Scope* scope = fun->scope(); 59 VisitDeclarations(scope->declarations()); 60 CHECK_BAILOUT; 61 62 VisitStatements(fun->body()); 63} 64 65 66void FullCodeGenSyntaxChecker::VisitDeclarations( 67 ZoneList<Declaration*>* decls) { 68 for (int i = 0; i < decls->length(); i++) { 69 Visit(decls->at(i)); 70 CHECK_BAILOUT; 71 } 72} 73 74 75void FullCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) { 76 for (int i = 0, len = stmts->length(); i < len; i++) { 77 Visit(stmts->at(i)); 78 CHECK_BAILOUT; 79 } 80} 81 82 83void FullCodeGenSyntaxChecker::VisitDeclaration(Declaration* decl) { 84 Property* prop = decl->proxy()->AsProperty(); 85 if (prop != NULL) { 86 Visit(prop->obj()); 87 Visit(prop->key()); 88 } 89 90 if (decl->fun() != NULL) { 91 Visit(decl->fun()); 92 } 93} 94 95 96void FullCodeGenSyntaxChecker::VisitBlock(Block* stmt) { 97 VisitStatements(stmt->statements()); 98} 99 100 101void FullCodeGenSyntaxChecker::VisitExpressionStatement( 102 ExpressionStatement* stmt) { 103 Visit(stmt->expression()); 104} 105 106 107void FullCodeGenSyntaxChecker::VisitEmptyStatement(EmptyStatement* stmt) { 108 // Supported. 109} 110 111 112void FullCodeGenSyntaxChecker::VisitIfStatement(IfStatement* stmt) { 113 Visit(stmt->condition()); 114 CHECK_BAILOUT; 115 Visit(stmt->then_statement()); 116 CHECK_BAILOUT; 117 Visit(stmt->else_statement()); 118} 119 120 121void FullCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) { 122 // Supported. 123} 124 125 126void FullCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) { 127 // Supported. 128} 129 130 131void FullCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) { 132 Visit(stmt->expression()); 133} 134 135 136void FullCodeGenSyntaxChecker::VisitWithEnterStatement( 137 WithEnterStatement* stmt) { 138 Visit(stmt->expression()); 139} 140 141 142void FullCodeGenSyntaxChecker::VisitWithExitStatement(WithExitStatement* stmt) { 143 // Supported. 144} 145 146 147void FullCodeGenSyntaxChecker::VisitSwitchStatement(SwitchStatement* stmt) { 148 BAILOUT("SwitchStatement"); 149} 150 151 152void FullCodeGenSyntaxChecker::VisitDoWhileStatement(DoWhileStatement* stmt) { 153 Visit(stmt->cond()); 154 CHECK_BAILOUT; 155 Visit(stmt->body()); 156} 157 158 159void FullCodeGenSyntaxChecker::VisitWhileStatement(WhileStatement* stmt) { 160 Visit(stmt->cond()); 161 CHECK_BAILOUT; 162 Visit(stmt->body()); 163} 164 165 166void FullCodeGenSyntaxChecker::VisitForStatement(ForStatement* stmt) { 167 if (!FLAG_always_full_compiler) BAILOUT("ForStatement"); 168 if (stmt->init() != NULL) { 169 Visit(stmt->init()); 170 CHECK_BAILOUT; 171 } 172 if (stmt->cond() != NULL) { 173 Visit(stmt->cond()); 174 CHECK_BAILOUT; 175 } 176 Visit(stmt->body()); 177 if (stmt->next() != NULL) { 178 CHECK_BAILOUT; 179 Visit(stmt->next()); 180 } 181} 182 183 184void FullCodeGenSyntaxChecker::VisitForInStatement(ForInStatement* stmt) { 185 BAILOUT("ForInStatement"); 186} 187 188 189void FullCodeGenSyntaxChecker::VisitTryCatchStatement(TryCatchStatement* stmt) { 190 Visit(stmt->try_block()); 191 CHECK_BAILOUT; 192 Visit(stmt->catch_block()); 193} 194 195 196void FullCodeGenSyntaxChecker::VisitTryFinallyStatement( 197 TryFinallyStatement* stmt) { 198 Visit(stmt->try_block()); 199 CHECK_BAILOUT; 200 Visit(stmt->finally_block()); 201} 202 203 204void FullCodeGenSyntaxChecker::VisitDebuggerStatement( 205 DebuggerStatement* stmt) { 206 // Supported. 207} 208 209 210void FullCodeGenSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) { 211 // Supported. 212} 213 214 215void FullCodeGenSyntaxChecker::VisitSharedFunctionInfoLiteral( 216 SharedFunctionInfoLiteral* expr) { 217 BAILOUT("SharedFunctionInfoLiteral"); 218} 219 220 221void FullCodeGenSyntaxChecker::VisitConditional(Conditional* expr) { 222 Visit(expr->condition()); 223 CHECK_BAILOUT; 224 Visit(expr->then_expression()); 225 CHECK_BAILOUT; 226 Visit(expr->else_expression()); 227} 228 229 230void FullCodeGenSyntaxChecker::VisitSlot(Slot* expr) { 231 UNREACHABLE(); 232} 233 234 235void FullCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) { 236 // Supported. 237} 238 239 240void FullCodeGenSyntaxChecker::VisitLiteral(Literal* expr) { 241 // Supported. 242} 243 244 245void FullCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) { 246 // Supported. 247} 248 249 250void FullCodeGenSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) { 251 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); 252 253 for (int i = 0, len = properties->length(); i < len; i++) { 254 ObjectLiteral::Property* property = properties->at(i); 255 if (property->IsCompileTimeValue()) continue; 256 Visit(property->key()); 257 CHECK_BAILOUT; 258 Visit(property->value()); 259 CHECK_BAILOUT; 260 } 261} 262 263 264void FullCodeGenSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) { 265 ZoneList<Expression*>* subexprs = expr->values(); 266 for (int i = 0, len = subexprs->length(); i < len; i++) { 267 Expression* subexpr = subexprs->at(i); 268 if (subexpr->AsLiteral() != NULL) continue; 269 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 270 Visit(subexpr); 271 CHECK_BAILOUT; 272 } 273} 274 275 276void FullCodeGenSyntaxChecker::VisitCatchExtensionObject( 277 CatchExtensionObject* expr) { 278 Visit(expr->key()); 279 CHECK_BAILOUT; 280 Visit(expr->value()); 281} 282 283 284void FullCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) { 285 Token::Value op = expr->op(); 286 if (op == Token::INIT_CONST) BAILOUT("initialize constant"); 287 288 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); 289 Property* prop = expr->target()->AsProperty(); 290 ASSERT(var == NULL || prop == NULL); 291 if (var != NULL) { 292 if (var->mode() == Variable::CONST) BAILOUT("Assignment to const"); 293 // All other variables are supported. 294 } else if (prop != NULL) { 295 Visit(prop->obj()); 296 CHECK_BAILOUT; 297 Visit(prop->key()); 298 CHECK_BAILOUT; 299 } else { 300 // This is a throw reference error. 301 BAILOUT("non-variable/non-property assignment"); 302 } 303 304 Visit(expr->value()); 305} 306 307 308void FullCodeGenSyntaxChecker::VisitThrow(Throw* expr) { 309 Visit(expr->exception()); 310} 311 312 313void FullCodeGenSyntaxChecker::VisitProperty(Property* expr) { 314 Visit(expr->obj()); 315 CHECK_BAILOUT; 316 Visit(expr->key()); 317} 318 319 320void FullCodeGenSyntaxChecker::VisitCall(Call* expr) { 321 Expression* fun = expr->expression(); 322 ZoneList<Expression*>* args = expr->arguments(); 323 Variable* var = fun->AsVariableProxy()->AsVariable(); 324 325 // Check for supported calls 326 if (var != NULL && var->is_possibly_eval()) { 327 BAILOUT("call to the identifier 'eval'"); 328 } else if (var != NULL && !var->is_this() && var->is_global()) { 329 // Calls to global variables are supported. 330 } else if (var != NULL && var->slot() != NULL && 331 var->slot()->type() == Slot::LOOKUP) { 332 BAILOUT("call to a lookup slot"); 333 } else if (fun->AsProperty() != NULL) { 334 Property* prop = fun->AsProperty(); 335 Visit(prop->obj()); 336 CHECK_BAILOUT; 337 Visit(prop->key()); 338 CHECK_BAILOUT; 339 } else { 340 // Otherwise the call is supported if the function expression is. 341 Visit(fun); 342 } 343 // Check all arguments to the call. 344 for (int i = 0; i < args->length(); i++) { 345 Visit(args->at(i)); 346 CHECK_BAILOUT; 347 } 348} 349 350 351void FullCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) { 352 Visit(expr->expression()); 353 CHECK_BAILOUT; 354 ZoneList<Expression*>* args = expr->arguments(); 355 // Check all arguments to the call 356 for (int i = 0; i < args->length(); i++) { 357 Visit(args->at(i)); 358 CHECK_BAILOUT; 359 } 360} 361 362 363void FullCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) { 364 // Check for inline runtime call 365 if (expr->name()->Get(0) == '_' && 366 CodeGenerator::FindInlineRuntimeLUT(expr->name()) != NULL) { 367 BAILOUT("inlined runtime call"); 368 } 369 // Check all arguments to the call. (Relies on TEMP meaning STACK.) 370 for (int i = 0; i < expr->arguments()->length(); i++) { 371 Visit(expr->arguments()->at(i)); 372 CHECK_BAILOUT; 373 } 374} 375 376 377void FullCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) { 378 switch (expr->op()) { 379 case Token::ADD: 380 case Token::BIT_NOT: 381 case Token::NOT: 382 case Token::SUB: 383 case Token::TYPEOF: 384 case Token::VOID: 385 Visit(expr->expression()); 386 break; 387 case Token::DELETE: 388 BAILOUT("UnaryOperation: DELETE"); 389 default: 390 UNREACHABLE(); 391 } 392} 393 394 395void FullCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) { 396 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 397 Property* prop = expr->expression()->AsProperty(); 398 ASSERT(var == NULL || prop == NULL); 399 if (var != NULL) { 400 // All global variables are supported. 401 if (!var->is_global()) { 402 ASSERT(var->slot() != NULL); 403 Slot::Type type = var->slot()->type(); 404 if (type == Slot::LOOKUP) { 405 BAILOUT("CountOperation with lookup slot"); 406 } 407 } 408 } else if (prop != NULL) { 409 Visit(prop->obj()); 410 CHECK_BAILOUT; 411 Visit(prop->key()); 412 CHECK_BAILOUT; 413 } else { 414 // This is a throw reference error. 415 BAILOUT("CountOperation non-variable/non-property expression"); 416 } 417} 418 419 420void FullCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) { 421 Visit(expr->left()); 422 CHECK_BAILOUT; 423 Visit(expr->right()); 424} 425 426 427void FullCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) { 428 Visit(expr->left()); 429 CHECK_BAILOUT; 430 Visit(expr->right()); 431} 432 433 434void FullCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) { 435 // Supported. 436} 437 438#undef BAILOUT 439#undef CHECK_BAILOUT 440 441 442void BreakableStatementChecker::Check(Statement* stmt) { 443 Visit(stmt); 444} 445 446 447void BreakableStatementChecker::Check(Expression* expr) { 448 Visit(expr); 449} 450 451 452void BreakableStatementChecker::VisitDeclaration(Declaration* decl) { 453} 454 455 456void BreakableStatementChecker::VisitBlock(Block* stmt) { 457} 458 459 460void BreakableStatementChecker::VisitExpressionStatement( 461 ExpressionStatement* stmt) { 462 // Check if expression is breakable. 463 Visit(stmt->expression()); 464} 465 466 467void BreakableStatementChecker::VisitEmptyStatement(EmptyStatement* stmt) { 468} 469 470 471void BreakableStatementChecker::VisitIfStatement(IfStatement* stmt) { 472 // If the condition is breakable the if statement is breakable. 473 Visit(stmt->condition()); 474} 475 476 477void BreakableStatementChecker::VisitContinueStatement( 478 ContinueStatement* stmt) { 479} 480 481 482void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) { 483} 484 485 486void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) { 487 // Return is breakable if the expression is. 488 Visit(stmt->expression()); 489} 490 491 492void BreakableStatementChecker::VisitWithEnterStatement( 493 WithEnterStatement* stmt) { 494 Visit(stmt->expression()); 495} 496 497 498void BreakableStatementChecker::VisitWithExitStatement( 499 WithExitStatement* stmt) { 500} 501 502 503void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) { 504 // Switch statements breakable if the tag expression is. 505 Visit(stmt->tag()); 506} 507 508 509void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) { 510 // Mark do while as breakable to avoid adding a break slot in front of it. 511 is_breakable_ = true; 512} 513 514 515void BreakableStatementChecker::VisitWhileStatement(WhileStatement* stmt) { 516 // Mark while statements breakable if the condition expression is. 517 Visit(stmt->cond()); 518} 519 520 521void BreakableStatementChecker::VisitForStatement(ForStatement* stmt) { 522 // Mark for statements breakable if the condition expression is. 523 if (stmt->cond() != NULL) { 524 Visit(stmt->cond()); 525 } 526} 527 528 529void BreakableStatementChecker::VisitForInStatement(ForInStatement* stmt) { 530 // Mark for in statements breakable if the enumerable expression is. 531 Visit(stmt->enumerable()); 532} 533 534 535void BreakableStatementChecker::VisitTryCatchStatement( 536 TryCatchStatement* stmt) { 537 // Mark try catch as breakable to avoid adding a break slot in front of it. 538 is_breakable_ = true; 539} 540 541 542void BreakableStatementChecker::VisitTryFinallyStatement( 543 TryFinallyStatement* stmt) { 544 // Mark try finally as breakable to avoid adding a break slot in front of it. 545 is_breakable_ = true; 546} 547 548 549void BreakableStatementChecker::VisitDebuggerStatement( 550 DebuggerStatement* stmt) { 551 // The debugger statement is breakable. 552 is_breakable_ = true; 553} 554 555 556void BreakableStatementChecker::VisitFunctionLiteral(FunctionLiteral* expr) { 557} 558 559 560void BreakableStatementChecker::VisitSharedFunctionInfoLiteral( 561 SharedFunctionInfoLiteral* expr) { 562} 563 564 565void BreakableStatementChecker::VisitConditional(Conditional* expr) { 566} 567 568 569void BreakableStatementChecker::VisitSlot(Slot* expr) { 570} 571 572 573void BreakableStatementChecker::VisitVariableProxy(VariableProxy* expr) { 574} 575 576 577void BreakableStatementChecker::VisitLiteral(Literal* expr) { 578} 579 580 581void BreakableStatementChecker::VisitRegExpLiteral(RegExpLiteral* expr) { 582} 583 584 585void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) { 586} 587 588 589void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) { 590} 591 592 593void BreakableStatementChecker::VisitCatchExtensionObject( 594 CatchExtensionObject* expr) { 595} 596 597 598void BreakableStatementChecker::VisitAssignment(Assignment* expr) { 599 // If assigning to a property (including a global property) the assignment is 600 // breakable. 601 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); 602 Property* prop = expr->target()->AsProperty(); 603 if (prop != NULL || (var != NULL && var->is_global())) { 604 is_breakable_ = true; 605 return; 606 } 607 608 // Otherwise the assignment is breakable if the assigned value is. 609 Visit(expr->value()); 610} 611 612 613void BreakableStatementChecker::VisitThrow(Throw* expr) { 614 // Throw is breakable if the expression is. 615 Visit(expr->exception()); 616} 617 618 619void BreakableStatementChecker::VisitProperty(Property* expr) { 620 // Property load is breakable. 621 is_breakable_ = true; 622} 623 624 625void BreakableStatementChecker::VisitCall(Call* expr) { 626 // Function calls both through IC and call stub are breakable. 627 is_breakable_ = true; 628} 629 630 631void BreakableStatementChecker::VisitCallNew(CallNew* expr) { 632 // Function calls through new are breakable. 633 is_breakable_ = true; 634} 635 636 637void BreakableStatementChecker::VisitCallRuntime(CallRuntime* expr) { 638} 639 640 641void BreakableStatementChecker::VisitUnaryOperation(UnaryOperation* expr) { 642 Visit(expr->expression()); 643} 644 645 646void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) { 647 Visit(expr->expression()); 648} 649 650 651void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) { 652 Visit(expr->left()); 653 Visit(expr->right()); 654} 655 656 657void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) { 658 Visit(expr->left()); 659 Visit(expr->right()); 660} 661 662 663void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) { 664} 665 666 667#define __ ACCESS_MASM(masm()) 668 669Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) { 670 Handle<Script> script = info->script(); 671 if (!script->IsUndefined() && !script->source()->IsUndefined()) { 672 int len = String::cast(script->source())->length(); 673 Counters::total_full_codegen_source_size.Increment(len); 674 } 675 CodeGenerator::MakeCodePrologue(info); 676 const int kInitialBufferSize = 4 * KB; 677 MacroAssembler masm(NULL, kInitialBufferSize); 678 679 FullCodeGenerator cgen(&masm); 680 cgen.Generate(info, PRIMARY); 681 if (cgen.HasStackOverflow()) { 682 ASSERT(!Top::has_pending_exception()); 683 return Handle<Code>::null(); 684 } 685 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP); 686 return CodeGenerator::MakeCodeEpilogue(&masm, flags, info); 687} 688 689 690int FullCodeGenerator::SlotOffset(Slot* slot) { 691 ASSERT(slot != NULL); 692 // Offset is negative because higher indexes are at lower addresses. 693 int offset = -slot->index() * kPointerSize; 694 // Adjust by a (parameter or local) base offset. 695 switch (slot->type()) { 696 case Slot::PARAMETER: 697 offset += (scope()->num_parameters() + 1) * kPointerSize; 698 break; 699 case Slot::LOCAL: 700 offset += JavaScriptFrameConstants::kLocal0Offset; 701 break; 702 case Slot::CONTEXT: 703 case Slot::LOOKUP: 704 UNREACHABLE(); 705 } 706 return offset; 707} 708 709 710void FullCodeGenerator::VisitDeclarations( 711 ZoneList<Declaration*>* declarations) { 712 int length = declarations->length(); 713 int globals = 0; 714 for (int i = 0; i < length; i++) { 715 Declaration* decl = declarations->at(i); 716 Variable* var = decl->proxy()->var(); 717 Slot* slot = var->slot(); 718 719 // If it was not possible to allocate the variable at compile 720 // time, we need to "declare" it at runtime to make sure it 721 // actually exists in the local context. 722 if ((slot != NULL && slot->type() == Slot::LOOKUP) || !var->is_global()) { 723 VisitDeclaration(decl); 724 } else { 725 // Count global variables and functions for later processing 726 globals++; 727 } 728 } 729 730 // Compute array of global variable and function declarations. 731 // Do nothing in case of no declared global functions or variables. 732 if (globals > 0) { 733 Handle<FixedArray> array = Factory::NewFixedArray(2 * globals, TENURED); 734 for (int j = 0, i = 0; i < length; i++) { 735 Declaration* decl = declarations->at(i); 736 Variable* var = decl->proxy()->var(); 737 Slot* slot = var->slot(); 738 739 if ((slot == NULL || slot->type() != Slot::LOOKUP) && var->is_global()) { 740 array->set(j++, *(var->name())); 741 if (decl->fun() == NULL) { 742 if (var->mode() == Variable::CONST) { 743 // In case this is const property use the hole. 744 array->set_the_hole(j++); 745 } else { 746 array->set_undefined(j++); 747 } 748 } else { 749 Handle<SharedFunctionInfo> function = 750 Compiler::BuildFunctionInfo(decl->fun(), script(), this); 751 // Check for stack-overflow exception. 752 if (HasStackOverflow()) return; 753 array->set(j++, *function); 754 } 755 } 756 } 757 // Invoke the platform-dependent code generator to do the actual 758 // declaration the global variables and functions. 759 DeclareGlobals(array); 760 } 761} 762 763 764void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) { 765 if (FLAG_debug_info) { 766 CodeGenerator::RecordPositions(masm_, fun->start_position()); 767 } 768} 769 770 771void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) { 772 if (FLAG_debug_info) { 773 CodeGenerator::RecordPositions(masm_, fun->end_position()); 774 } 775} 776 777 778void FullCodeGenerator::SetStatementPosition(Statement* stmt) { 779 if (FLAG_debug_info) { 780#ifdef ENABLE_DEBUGGER_SUPPORT 781 if (!Debugger::IsDebuggerActive()) { 782 CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); 783 } else { 784 // Check if the statement will be breakable without adding a debug break 785 // slot. 786 BreakableStatementChecker checker; 787 checker.Check(stmt); 788 // Record the statement position right here if the statement is not 789 // breakable. For breakable statements the actual recording of the 790 // position will be postponed to the breakable code (typically an IC). 791 bool position_recorded = CodeGenerator::RecordPositions( 792 masm_, stmt->statement_pos(), !checker.is_breakable()); 793 // If the position recording did record a new position generate a debug 794 // break slot to make the statement breakable. 795 if (position_recorded) { 796 Debug::GenerateSlot(masm_); 797 } 798 } 799#else 800 CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); 801#endif 802 } 803} 804 805 806void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) { 807 if (FLAG_debug_info) { 808#ifdef ENABLE_DEBUGGER_SUPPORT 809 if (!Debugger::IsDebuggerActive()) { 810 CodeGenerator::RecordPositions(masm_, pos); 811 } else { 812 // Check if the expression will be breakable without adding a debug break 813 // slot. 814 BreakableStatementChecker checker; 815 checker.Check(expr); 816 // Record a statement position right here if the expression is not 817 // breakable. For breakable expressions the actual recording of the 818 // position will be postponed to the breakable code (typically an IC). 819 // NOTE this will record a statement position for something which might 820 // not be a statement. As stepping in the debugger will only stop at 821 // statement positions this is used for e.g. the condition expression of 822 // a do while loop. 823 bool position_recorded = CodeGenerator::RecordPositions( 824 masm_, pos, !checker.is_breakable()); 825 // If the position recording did record a new position generate a debug 826 // break slot to make the statement breakable. 827 if (position_recorded) { 828 Debug::GenerateSlot(masm_); 829 } 830 } 831#else 832 CodeGenerator::RecordPositions(masm_, pos); 833#endif 834 } 835} 836 837 838void FullCodeGenerator::SetStatementPosition(int pos) { 839 if (FLAG_debug_info) { 840 CodeGenerator::RecordPositions(masm_, pos); 841 } 842} 843 844 845void FullCodeGenerator::SetSourcePosition(int pos) { 846 if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { 847 masm_->RecordPosition(pos); 848 } 849} 850 851 852void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { 853 Handle<String> name = expr->name(); 854 if (strcmp("_IsSmi", *name->ToCString()) == 0) { 855 EmitIsSmi(expr->arguments()); 856 } else if (strcmp("_IsNonNegativeSmi", *name->ToCString()) == 0) { 857 EmitIsNonNegativeSmi(expr->arguments()); 858 } else if (strcmp("_IsObject", *name->ToCString()) == 0) { 859 EmitIsObject(expr->arguments()); 860 } else if (strcmp("_IsSpecObject", *name->ToCString()) == 0) { 861 EmitIsSpecObject(expr->arguments()); 862 } else if (strcmp("_IsUndetectableObject", *name->ToCString()) == 0) { 863 EmitIsUndetectableObject(expr->arguments()); 864 } else if (strcmp("_IsFunction", *name->ToCString()) == 0) { 865 EmitIsFunction(expr->arguments()); 866 } else if (strcmp("_IsArray", *name->ToCString()) == 0) { 867 EmitIsArray(expr->arguments()); 868 } else if (strcmp("_IsRegExp", *name->ToCString()) == 0) { 869 EmitIsRegExp(expr->arguments()); 870 } else if (strcmp("_IsConstructCall", *name->ToCString()) == 0) { 871 EmitIsConstructCall(expr->arguments()); 872 } else if (strcmp("_ObjectEquals", *name->ToCString()) == 0) { 873 EmitObjectEquals(expr->arguments()); 874 } else if (strcmp("_Arguments", *name->ToCString()) == 0) { 875 EmitArguments(expr->arguments()); 876 } else if (strcmp("_ArgumentsLength", *name->ToCString()) == 0) { 877 EmitArgumentsLength(expr->arguments()); 878 } else if (strcmp("_ClassOf", *name->ToCString()) == 0) { 879 EmitClassOf(expr->arguments()); 880 } else if (strcmp("_Log", *name->ToCString()) == 0) { 881 EmitLog(expr->arguments()); 882 } else if (strcmp("_RandomHeapNumber", *name->ToCString()) == 0) { 883 EmitRandomHeapNumber(expr->arguments()); 884 } else if (strcmp("_SubString", *name->ToCString()) == 0) { 885 EmitSubString(expr->arguments()); 886 } else if (strcmp("_RegExpExec", *name->ToCString()) == 0) { 887 EmitRegExpExec(expr->arguments()); 888 } else if (strcmp("_ValueOf", *name->ToCString()) == 0) { 889 EmitValueOf(expr->arguments()); 890 } else if (strcmp("_SetValueOf", *name->ToCString()) == 0) { 891 EmitSetValueOf(expr->arguments()); 892 } else if (strcmp("_NumberToString", *name->ToCString()) == 0) { 893 EmitNumberToString(expr->arguments()); 894 } else if (strcmp("_StringCharFromCode", *name->ToCString()) == 0) { 895 EmitStringCharFromCode(expr->arguments()); 896 } else if (strcmp("_StringCharCodeAt", *name->ToCString()) == 0) { 897 EmitStringCharCodeAt(expr->arguments()); 898 } else if (strcmp("_StringCharAt", *name->ToCString()) == 0) { 899 EmitStringCharAt(expr->arguments()); 900 } else if (strcmp("_StringAdd", *name->ToCString()) == 0) { 901 EmitStringAdd(expr->arguments()); 902 } else if (strcmp("_StringCompare", *name->ToCString()) == 0) { 903 EmitStringCompare(expr->arguments()); 904 } else if (strcmp("_MathPow", *name->ToCString()) == 0) { 905 EmitMathPow(expr->arguments()); 906 } else if (strcmp("_MathSin", *name->ToCString()) == 0) { 907 EmitMathSin(expr->arguments()); 908 } else if (strcmp("_MathCos", *name->ToCString()) == 0) { 909 EmitMathCos(expr->arguments()); 910 } else if (strcmp("_MathSqrt", *name->ToCString()) == 0) { 911 EmitMathSqrt(expr->arguments()); 912 } else if (strcmp("_CallFunction", *name->ToCString()) == 0) { 913 EmitCallFunction(expr->arguments()); 914 } else if (strcmp("_RegExpConstructResult", *name->ToCString()) == 0) { 915 EmitRegExpConstructResult(expr->arguments()); 916 } else if (strcmp("_SwapElements", *name->ToCString()) == 0) { 917 EmitSwapElements(expr->arguments()); 918 } else if (strcmp("_GetFromCache", *name->ToCString()) == 0) { 919 EmitGetFromCache(expr->arguments()); 920 } else { 921 UNREACHABLE(); 922 } 923} 924 925 926void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { 927 Label eval_right, done; 928 929 // Set up the appropriate context for the left subexpression based 930 // on the operation and our own context. Initially assume we can 931 // inherit both true and false labels from our context. 932 if (expr->op() == Token::OR) { 933 switch (context_) { 934 case Expression::kUninitialized: 935 UNREACHABLE(); 936 case Expression::kEffect: 937 VisitForControl(expr->left(), &done, &eval_right); 938 break; 939 case Expression::kValue: 940 VisitForValueControl(expr->left(), 941 location_, 942 &done, 943 &eval_right); 944 break; 945 case Expression::kTest: 946 VisitForControl(expr->left(), true_label_, &eval_right); 947 break; 948 case Expression::kValueTest: 949 VisitForValueControl(expr->left(), 950 location_, 951 true_label_, 952 &eval_right); 953 break; 954 case Expression::kTestValue: 955 VisitForControl(expr->left(), true_label_, &eval_right); 956 break; 957 } 958 } else { 959 ASSERT_EQ(Token::AND, expr->op()); 960 switch (context_) { 961 case Expression::kUninitialized: 962 UNREACHABLE(); 963 case Expression::kEffect: 964 VisitForControl(expr->left(), &eval_right, &done); 965 break; 966 case Expression::kValue: 967 VisitForControlValue(expr->left(), 968 location_, 969 &eval_right, 970 &done); 971 break; 972 case Expression::kTest: 973 VisitForControl(expr->left(), &eval_right, false_label_); 974 break; 975 case Expression::kValueTest: 976 VisitForControl(expr->left(), &eval_right, false_label_); 977 break; 978 case Expression::kTestValue: 979 VisitForControlValue(expr->left(), 980 location_, 981 &eval_right, 982 false_label_); 983 break; 984 } 985 } 986 987 __ bind(&eval_right); 988 Visit(expr->right()); 989 990 __ bind(&done); 991} 992 993 994void FullCodeGenerator::VisitBlock(Block* stmt) { 995 Comment cmnt(masm_, "[ Block"); 996 Breakable nested_statement(this, stmt); 997 SetStatementPosition(stmt); 998 VisitStatements(stmt->statements()); 999 __ bind(nested_statement.break_target()); 1000} 1001 1002 1003void FullCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 1004 Comment cmnt(masm_, "[ ExpressionStatement"); 1005 SetStatementPosition(stmt); 1006 VisitForEffect(stmt->expression()); 1007} 1008 1009 1010void FullCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 1011 Comment cmnt(masm_, "[ EmptyStatement"); 1012 SetStatementPosition(stmt); 1013} 1014 1015 1016void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) { 1017 Comment cmnt(masm_, "[ IfStatement"); 1018 SetStatementPosition(stmt); 1019 Label then_part, else_part, done; 1020 1021 // Do not worry about optimizing for empty then or else bodies. 1022 VisitForControl(stmt->condition(), &then_part, &else_part); 1023 1024 __ bind(&then_part); 1025 Visit(stmt->then_statement()); 1026 __ jmp(&done); 1027 1028 __ bind(&else_part); 1029 Visit(stmt->else_statement()); 1030 1031 __ bind(&done); 1032} 1033 1034 1035void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { 1036 Comment cmnt(masm_, "[ ContinueStatement"); 1037 SetStatementPosition(stmt); 1038 NestedStatement* current = nesting_stack_; 1039 int stack_depth = 0; 1040 while (!current->IsContinueTarget(stmt->target())) { 1041 stack_depth = current->Exit(stack_depth); 1042 current = current->outer(); 1043 } 1044 __ Drop(stack_depth); 1045 1046 Iteration* loop = current->AsIteration(); 1047 __ jmp(loop->continue_target()); 1048} 1049 1050 1051void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 1052 Comment cmnt(masm_, "[ BreakStatement"); 1053 SetStatementPosition(stmt); 1054 NestedStatement* current = nesting_stack_; 1055 int stack_depth = 0; 1056 while (!current->IsBreakTarget(stmt->target())) { 1057 stack_depth = current->Exit(stack_depth); 1058 current = current->outer(); 1059 } 1060 __ Drop(stack_depth); 1061 1062 Breakable* target = current->AsBreakable(); 1063 __ jmp(target->break_target()); 1064} 1065 1066 1067void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 1068 Comment cmnt(masm_, "[ ReturnStatement"); 1069 SetStatementPosition(stmt); 1070 Expression* expr = stmt->expression(); 1071 VisitForValue(expr, kAccumulator); 1072 1073 // Exit all nested statements. 1074 NestedStatement* current = nesting_stack_; 1075 int stack_depth = 0; 1076 while (current != NULL) { 1077 stack_depth = current->Exit(stack_depth); 1078 current = current->outer(); 1079 } 1080 __ Drop(stack_depth); 1081 1082 EmitReturnSequence(); 1083} 1084 1085 1086void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { 1087 Comment cmnt(masm_, "[ WithEnterStatement"); 1088 SetStatementPosition(stmt); 1089 1090 VisitForValue(stmt->expression(), kStack); 1091 if (stmt->is_catch_block()) { 1092 __ CallRuntime(Runtime::kPushCatchContext, 1); 1093 } else { 1094 __ CallRuntime(Runtime::kPushContext, 1); 1095 } 1096 // Both runtime calls return the new context in both the context and the 1097 // result registers. 1098 1099 // Update local stack frame context field. 1100 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); 1101} 1102 1103 1104void FullCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) { 1105 Comment cmnt(masm_, "[ WithExitStatement"); 1106 SetStatementPosition(stmt); 1107 1108 // Pop context. 1109 LoadContextField(context_register(), Context::PREVIOUS_INDEX); 1110 // Update local stack frame context field. 1111 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); 1112} 1113 1114 1115void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 1116 Comment cmnt(masm_, "[ DoWhileStatement"); 1117 SetStatementPosition(stmt); 1118 Label body, stack_limit_hit, stack_check_success; 1119 1120 Iteration loop_statement(this, stmt); 1121 increment_loop_depth(); 1122 1123 __ bind(&body); 1124 Visit(stmt->body()); 1125 1126 // Check stack before looping. 1127 __ StackLimitCheck(&stack_limit_hit); 1128 __ bind(&stack_check_success); 1129 1130 __ bind(loop_statement.continue_target()); 1131 1132 // Record the position of the do while condition and make sure it is possible 1133 // to break on the condition. 1134 SetExpressionPosition(stmt->cond(), stmt->condition_position()); 1135 1136 VisitForControl(stmt->cond(), &body, loop_statement.break_target()); 1137 1138 __ bind(&stack_limit_hit); 1139 StackCheckStub stack_stub; 1140 __ CallStub(&stack_stub); 1141 __ jmp(&stack_check_success); 1142 1143 __ bind(loop_statement.break_target()); 1144 1145 decrement_loop_depth(); 1146} 1147 1148 1149void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 1150 Comment cmnt(masm_, "[ WhileStatement"); 1151 Label body, stack_limit_hit, stack_check_success; 1152 1153 Iteration loop_statement(this, stmt); 1154 increment_loop_depth(); 1155 1156 // Emit the test at the bottom of the loop. 1157 __ jmp(loop_statement.continue_target()); 1158 1159 __ bind(&body); 1160 Visit(stmt->body()); 1161 1162 __ bind(loop_statement.continue_target()); 1163 // Emit the statement position here as this is where the while statement code 1164 // starts. 1165 SetStatementPosition(stmt); 1166 1167 // Check stack before looping. 1168 __ StackLimitCheck(&stack_limit_hit); 1169 __ bind(&stack_check_success); 1170 1171 VisitForControl(stmt->cond(), &body, loop_statement.break_target()); 1172 1173 __ bind(&stack_limit_hit); 1174 StackCheckStub stack_stub; 1175 __ CallStub(&stack_stub); 1176 __ jmp(&stack_check_success); 1177 1178 __ bind(loop_statement.break_target()); 1179 decrement_loop_depth(); 1180} 1181 1182 1183void FullCodeGenerator::VisitForStatement(ForStatement* stmt) { 1184 Comment cmnt(masm_, "[ ForStatement"); 1185 Label test, body, stack_limit_hit, stack_check_success; 1186 1187 Iteration loop_statement(this, stmt); 1188 if (stmt->init() != NULL) { 1189 Visit(stmt->init()); 1190 } 1191 1192 increment_loop_depth(); 1193 // Emit the test at the bottom of the loop (even if empty). 1194 __ jmp(&test); 1195 1196 __ bind(&body); 1197 Visit(stmt->body()); 1198 1199 __ bind(loop_statement.continue_target()); 1200 1201 SetStatementPosition(stmt); 1202 if (stmt->next() != NULL) { 1203 Visit(stmt->next()); 1204 } 1205 1206 __ bind(&test); 1207 // Emit the statement position here as this is where the for statement code 1208 // starts. 1209 SetStatementPosition(stmt); 1210 1211 // Check stack before looping. 1212 __ StackLimitCheck(&stack_limit_hit); 1213 __ bind(&stack_check_success); 1214 1215 if (stmt->cond() != NULL) { 1216 VisitForControl(stmt->cond(), &body, loop_statement.break_target()); 1217 } else { 1218 __ jmp(&body); 1219 } 1220 1221 __ bind(&stack_limit_hit); 1222 StackCheckStub stack_stub; 1223 __ CallStub(&stack_stub); 1224 __ jmp(&stack_check_success); 1225 1226 __ bind(loop_statement.break_target()); 1227 decrement_loop_depth(); 1228} 1229 1230 1231void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { 1232 Comment cmnt(masm_, "[ TryCatchStatement"); 1233 SetStatementPosition(stmt); 1234 // The try block adds a handler to the exception handler chain 1235 // before entering, and removes it again when exiting normally. 1236 // If an exception is thrown during execution of the try block, 1237 // control is passed to the handler, which also consumes the handler. 1238 // At this point, the exception is in a register, and store it in 1239 // the temporary local variable (prints as ".catch-var") before 1240 // executing the catch block. The catch block has been rewritten 1241 // to introduce a new scope to bind the catch variable and to remove 1242 // that scope again afterwards. 1243 1244 Label try_handler_setup, catch_entry, done; 1245 __ Call(&try_handler_setup); 1246 // Try handler code, exception in result register. 1247 1248 // Store exception in local .catch variable before executing catch block. 1249 { 1250 // The catch variable is *always* a variable proxy for a local variable. 1251 Variable* catch_var = stmt->catch_var()->AsVariableProxy()->AsVariable(); 1252 ASSERT_NOT_NULL(catch_var); 1253 Slot* variable_slot = catch_var->slot(); 1254 ASSERT_NOT_NULL(variable_slot); 1255 ASSERT_EQ(Slot::LOCAL, variable_slot->type()); 1256 StoreToFrameField(SlotOffset(variable_slot), result_register()); 1257 } 1258 1259 Visit(stmt->catch_block()); 1260 __ jmp(&done); 1261 1262 // Try block code. Sets up the exception handler chain. 1263 __ bind(&try_handler_setup); 1264 { 1265 TryCatch try_block(this, &catch_entry); 1266 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); 1267 Visit(stmt->try_block()); 1268 __ PopTryHandler(); 1269 } 1270 __ bind(&done); 1271} 1272 1273 1274void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 1275 Comment cmnt(masm_, "[ TryFinallyStatement"); 1276 SetStatementPosition(stmt); 1277 // Try finally is compiled by setting up a try-handler on the stack while 1278 // executing the try body, and removing it again afterwards. 1279 // 1280 // The try-finally construct can enter the finally block in three ways: 1281 // 1. By exiting the try-block normally. This removes the try-handler and 1282 // calls the finally block code before continuing. 1283 // 2. By exiting the try-block with a function-local control flow transfer 1284 // (break/continue/return). The site of the, e.g., break removes the 1285 // try handler and calls the finally block code before continuing 1286 // its outward control transfer. 1287 // 3. by exiting the try-block with a thrown exception. 1288 // This can happen in nested function calls. It traverses the try-handler 1289 // chain and consumes the try-handler entry before jumping to the 1290 // handler code. The handler code then calls the finally-block before 1291 // rethrowing the exception. 1292 // 1293 // The finally block must assume a return address on top of the stack 1294 // (or in the link register on ARM chips) and a value (return value or 1295 // exception) in the result register (rax/eax/r0), both of which must 1296 // be preserved. The return address isn't GC-safe, so it should be 1297 // cooked before GC. 1298 Label finally_entry; 1299 Label try_handler_setup; 1300 1301 // Setup the try-handler chain. Use a call to 1302 // Jump to try-handler setup and try-block code. Use call to put try-handler 1303 // address on stack. 1304 __ Call(&try_handler_setup); 1305 // Try handler code. Return address of call is pushed on handler stack. 1306 { 1307 // This code is only executed during stack-handler traversal when an 1308 // exception is thrown. The execption is in the result register, which 1309 // is retained by the finally block. 1310 // Call the finally block and then rethrow the exception. 1311 __ Call(&finally_entry); 1312 __ push(result_register()); 1313 __ CallRuntime(Runtime::kReThrow, 1); 1314 } 1315 1316 __ bind(&finally_entry); 1317 { 1318 // Finally block implementation. 1319 Finally finally_block(this); 1320 EnterFinallyBlock(); 1321 Visit(stmt->finally_block()); 1322 ExitFinallyBlock(); // Return to the calling code. 1323 } 1324 1325 __ bind(&try_handler_setup); 1326 { 1327 // Setup try handler (stack pointer registers). 1328 TryFinally try_block(this, &finally_entry); 1329 __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER); 1330 Visit(stmt->try_block()); 1331 __ PopTryHandler(); 1332 } 1333 // Execute the finally block on the way out. 1334 __ Call(&finally_entry); 1335} 1336 1337 1338void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { 1339#ifdef ENABLE_DEBUGGER_SUPPORT 1340 Comment cmnt(masm_, "[ DebuggerStatement"); 1341 SetStatementPosition(stmt); 1342 1343 __ DebugBreak(); 1344 // Ignore the return value. 1345#endif 1346} 1347 1348 1349void FullCodeGenerator::VisitConditional(Conditional* expr) { 1350 Comment cmnt(masm_, "[ Conditional"); 1351 Label true_case, false_case, done; 1352 VisitForControl(expr->condition(), &true_case, &false_case); 1353 1354 __ bind(&true_case); 1355 SetExpressionPosition(expr->then_expression(), 1356 expr->then_expression_position()); 1357 Visit(expr->then_expression()); 1358 // If control flow falls through Visit, jump to done. 1359 if (context_ == Expression::kEffect || context_ == Expression::kValue) { 1360 __ jmp(&done); 1361 } 1362 1363 __ bind(&false_case); 1364 SetExpressionPosition(expr->else_expression(), 1365 expr->else_expression_position()); 1366 Visit(expr->else_expression()); 1367 // If control flow falls through Visit, merge it with true case here. 1368 if (context_ == Expression::kEffect || context_ == Expression::kValue) { 1369 __ bind(&done); 1370 } 1371} 1372 1373 1374void FullCodeGenerator::VisitSlot(Slot* expr) { 1375 // Slots do not appear directly in the AST. 1376 UNREACHABLE(); 1377} 1378 1379 1380void FullCodeGenerator::VisitLiteral(Literal* expr) { 1381 Comment cmnt(masm_, "[ Literal"); 1382 Apply(context_, expr); 1383} 1384 1385 1386void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 1387 Comment cmnt(masm_, "[ FunctionLiteral"); 1388 1389 // Build the function boilerplate and instantiate it. 1390 Handle<SharedFunctionInfo> function_info = 1391 Compiler::BuildFunctionInfo(expr, script(), this); 1392 if (HasStackOverflow()) return; 1393 EmitNewClosure(function_info); 1394} 1395 1396 1397void FullCodeGenerator::VisitSharedFunctionInfoLiteral( 1398 SharedFunctionInfoLiteral* expr) { 1399 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral"); 1400 EmitNewClosure(expr->shared_function_info()); 1401} 1402 1403 1404void FullCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { 1405 // Call runtime routine to allocate the catch extension object and 1406 // assign the exception value to the catch variable. 1407 Comment cmnt(masm_, "[ CatchExtensionObject"); 1408 VisitForValue(expr->key(), kStack); 1409 VisitForValue(expr->value(), kStack); 1410 // Create catch extension object. 1411 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); 1412 Apply(context_, result_register()); 1413} 1414 1415 1416void FullCodeGenerator::VisitThrow(Throw* expr) { 1417 Comment cmnt(masm_, "[ Throw"); 1418 VisitForValue(expr->exception(), kStack); 1419 __ CallRuntime(Runtime::kThrow, 1); 1420 // Never returns here. 1421} 1422 1423 1424int FullCodeGenerator::TryFinally::Exit(int stack_depth) { 1425 // The macros used here must preserve the result register. 1426 __ Drop(stack_depth); 1427 __ PopTryHandler(); 1428 __ Call(finally_entry_); 1429 return 0; 1430} 1431 1432 1433int FullCodeGenerator::TryCatch::Exit(int stack_depth) { 1434 // The macros used here must preserve the result register. 1435 __ Drop(stack_depth); 1436 __ PopTryHandler(); 1437 return 0; 1438} 1439 1440#undef __ 1441 1442 1443} } // namespace v8::internal 1444