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