Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: src/full-codegen.cc

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/full-codegen.h ('k') | src/func-name-inferrer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) { 83 void BreakableStatementChecker::VisitBreakStatement(BreakStatement* stmt) {
84 } 84 }
85 85
86 86
87 void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) { 87 void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) {
88 // Return is breakable if the expression is. 88 // Return is breakable if the expression is.
89 Visit(stmt->expression()); 89 Visit(stmt->expression());
90 } 90 }
91 91
92 92
93 void BreakableStatementChecker::VisitWithEnterStatement( 93 void BreakableStatementChecker::VisitEnterWithContextStatement(
94 WithEnterStatement* stmt) { 94 EnterWithContextStatement* stmt) {
95 Visit(stmt->expression()); 95 Visit(stmt->expression());
96 } 96 }
97 97
98 98
99 void BreakableStatementChecker::VisitWithExitStatement( 99 void BreakableStatementChecker::VisitExitContextStatement(
100 WithExitStatement* stmt) { 100 ExitContextStatement* stmt) {
101 } 101 }
102 102
103 103
104 void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) { 104 void BreakableStatementChecker::VisitSwitchStatement(SwitchStatement* stmt) {
105 // Switch statements breakable if the tag expression is. 105 // Switch statements breakable if the tag expression is.
106 Visit(stmt->tag()); 106 Visit(stmt->tag());
107 } 107 }
108 108
109 109
110 void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) { 110 void BreakableStatementChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 180
181 181
182 void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) { 182 void BreakableStatementChecker::VisitObjectLiteral(ObjectLiteral* expr) {
183 } 183 }
184 184
185 185
186 void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) { 186 void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) {
187 } 187 }
188 188
189 189
190 void BreakableStatementChecker::VisitCatchExtensionObject(
191 CatchExtensionObject* expr) {
192 }
193
194
195 void BreakableStatementChecker::VisitAssignment(Assignment* expr) { 190 void BreakableStatementChecker::VisitAssignment(Assignment* expr) {
196 // If assigning to a property (including a global property) the assignment is 191 // If assigning to a property (including a global property) the assignment is
197 // breakable. 192 // breakable.
198 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); 193 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
199 Property* prop = expr->target()->AsProperty(); 194 Property* prop = expr->target()->AsProperty();
200 if (prop != NULL || (var != NULL && var->is_global())) { 195 if (prop != NULL || (var != NULL && var->is_global())) {
201 is_breakable_ = true; 196 is_breakable_ = true;
202 return; 197 return;
203 } 198 }
204 199
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 } 235 }
241 236
242 237
243 void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) { 238 void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) {
244 Visit(expr->expression()); 239 Visit(expr->expression());
245 } 240 }
246 241
247 242
248 void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) { 243 void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) {
249 Visit(expr->left()); 244 Visit(expr->left());
250 Visit(expr->right()); 245 if (expr->op() != Token::AND &&
246 expr->op() != Token::OR) {
247 Visit(expr->right());
248 }
251 } 249 }
252 250
253 251
254 void BreakableStatementChecker::VisitCompareToNull(CompareToNull* expr) { 252 void BreakableStatementChecker::VisitCompareToNull(CompareToNull* expr) {
255 Visit(expr->expression()); 253 Visit(expr->expression());
256 } 254 }
257 255
258 256
259 void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) { 257 void BreakableStatementChecker::VisitCompareOperation(CompareOperation* expr) {
260 Visit(expr->left()); 258 Visit(expr->left());
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 isolate()->factory()-> 339 isolate()->factory()->
342 NewDeoptimizationOutputData(length, TENURED); 340 NewDeoptimizationOutputData(length, TENURED);
343 for (int i = 0; i < length; i++) { 341 for (int i = 0; i < length; i++) {
344 data->SetAstId(i, Smi::FromInt(bailout_entries_[i].id)); 342 data->SetAstId(i, Smi::FromInt(bailout_entries_[i].id));
345 data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state)); 343 data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state));
346 } 344 }
347 code->set_deoptimization_data(*data); 345 code->set_deoptimization_data(*data);
348 } 346 }
349 347
350 348
351 void FullCodeGenerator::PrepareForBailout(AstNode* node, State state) { 349 void FullCodeGenerator::PrepareForBailout(Expression* node, State state) {
352 PrepareForBailoutForId(node->id(), state); 350 PrepareForBailoutForId(node->id(), state);
353 } 351 }
354 352
355 353
356 void FullCodeGenerator::RecordJSReturnSite(Call* call) { 354 void FullCodeGenerator::RecordJSReturnSite(Call* call) {
357 // We record the offset of the function return so we can rebuild the frame 355 // We record the offset of the function return so we can rebuild the frame
358 // if the function was inlined, i.e., this is the return address in the 356 // if the function was inlined, i.e., this is the return address in the
359 // inlined function's frame. 357 // inlined function's frame.
360 // 358 //
361 // The state is ignored. We defensively set it to TOS_REG, which is the 359 // The state is ignored. We defensively set it to TOS_REG, which is the
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 } 397 }
400 398
401 399
402 int FullCodeGenerator::SlotOffset(Slot* slot) { 400 int FullCodeGenerator::SlotOffset(Slot* slot) {
403 ASSERT(slot != NULL); 401 ASSERT(slot != NULL);
404 // Offset is negative because higher indexes are at lower addresses. 402 // Offset is negative because higher indexes are at lower addresses.
405 int offset = -slot->index() * kPointerSize; 403 int offset = -slot->index() * kPointerSize;
406 // Adjust by a (parameter or local) base offset. 404 // Adjust by a (parameter or local) base offset.
407 switch (slot->type()) { 405 switch (slot->type()) {
408 case Slot::PARAMETER: 406 case Slot::PARAMETER:
409 offset += (scope()->num_parameters() + 1) * kPointerSize; 407 offset += (info_->scope()->num_parameters() + 1) * kPointerSize;
410 break; 408 break;
411 case Slot::LOCAL: 409 case Slot::LOCAL:
412 offset += JavaScriptFrameConstants::kLocal0Offset; 410 offset += JavaScriptFrameConstants::kLocal0Offset;
413 break; 411 break;
414 case Slot::CONTEXT: 412 case Slot::CONTEXT:
415 case Slot::LOOKUP: 413 case Slot::LOOKUP:
416 UNREACHABLE(); 414 UNREACHABLE();
417 } 415 }
418 return offset; 416 return offset;
419 } 417 }
(...skipping 19 matching lines...) Expand all
439 437
440 void FullCodeGenerator::StackValueContext::Plug(Register reg) const { 438 void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
441 __ push(reg); 439 __ push(reg);
442 } 440 }
443 441
444 442
445 void FullCodeGenerator::TestContext::Plug(Register reg) const { 443 void FullCodeGenerator::TestContext::Plug(Register reg) const {
446 // For simplicity we always test the accumulator register. 444 // For simplicity we always test the accumulator register.
447 __ Move(result_register(), reg); 445 __ Move(result_register(), reg);
448 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 446 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
449 codegen()->DoTest(true_label_, false_label_, fall_through_); 447 codegen()->DoTest(this);
450 } 448 }
451 449
452 450
453 void FullCodeGenerator::EffectContext::PlugTOS() const { 451 void FullCodeGenerator::EffectContext::PlugTOS() const {
454 __ Drop(1); 452 __ Drop(1);
455 } 453 }
456 454
457 455
458 void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const { 456 void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
459 __ pop(result_register()); 457 __ pop(result_register());
460 } 458 }
461 459
462 460
463 void FullCodeGenerator::StackValueContext::PlugTOS() const { 461 void FullCodeGenerator::StackValueContext::PlugTOS() const {
464 } 462 }
465 463
466 464
467 void FullCodeGenerator::TestContext::PlugTOS() const { 465 void FullCodeGenerator::TestContext::PlugTOS() const {
468 // For simplicity we always test the accumulator register. 466 // For simplicity we always test the accumulator register.
469 __ pop(result_register()); 467 __ pop(result_register());
470 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 468 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
471 codegen()->DoTest(true_label_, false_label_, fall_through_); 469 codegen()->DoTest(this);
472 } 470 }
473 471
474 472
475 void FullCodeGenerator::EffectContext::PrepareTest( 473 void FullCodeGenerator::EffectContext::PrepareTest(
476 Label* materialize_true, 474 Label* materialize_true,
477 Label* materialize_false, 475 Label* materialize_false,
478 Label** if_true, 476 Label** if_true,
479 Label** if_false, 477 Label** if_false,
480 Label** fall_through) const { 478 Label** fall_through) const {
481 // In an effect context, the true and the false case branch to the 479 // In an effect context, the true and the false case branch to the
(...skipping 29 matching lines...) Expand all
511 Label* materialize_false, 509 Label* materialize_false,
512 Label** if_true, 510 Label** if_true,
513 Label** if_false, 511 Label** if_false,
514 Label** fall_through) const { 512 Label** fall_through) const {
515 *if_true = true_label_; 513 *if_true = true_label_;
516 *if_false = false_label_; 514 *if_false = false_label_;
517 *fall_through = fall_through_; 515 *fall_through = fall_through_;
518 } 516 }
519 517
520 518
519 void FullCodeGenerator::DoTest(const TestContext* context) {
520 DoTest(context->condition(),
521 context->true_label(),
522 context->false_label(),
523 context->fall_through());
524 }
525
526
521 void FullCodeGenerator::VisitDeclarations( 527 void FullCodeGenerator::VisitDeclarations(
522 ZoneList<Declaration*>* declarations) { 528 ZoneList<Declaration*>* declarations) {
523 int length = declarations->length(); 529 int length = declarations->length();
524 int globals = 0; 530 int globals = 0;
525 for (int i = 0; i < length; i++) { 531 for (int i = 0; i < length; i++) {
526 Declaration* decl = declarations->at(i); 532 Declaration* decl = declarations->at(i);
527 Variable* var = decl->proxy()->var(); 533 Variable* var = decl->proxy()->var();
528 Slot* slot = var->AsSlot(); 534 Slot* slot = var->AsSlot();
529 535
530 // If it was not possible to allocate the variable at compile 536 // If it was not possible to allocate the variable at compile
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 } 576 }
571 } 577 }
572 // Invoke the platform-dependent code generator to do the actual 578 // Invoke the platform-dependent code generator to do the actual
573 // declaration the global variables and functions. 579 // declaration the global variables and functions.
574 DeclareGlobals(array); 580 DeclareGlobals(array);
575 } 581 }
576 } 582 }
577 583
578 584
579 void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) { 585 void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
580 if (FLAG_debug_info) { 586 CodeGenerator::RecordPositions(masm_, fun->start_position());
581 CodeGenerator::RecordPositions(masm_, fun->start_position());
582 }
583 } 587 }
584 588
585 589
586 void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) { 590 void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) {
587 if (FLAG_debug_info) { 591 CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
588 CodeGenerator::RecordPositions(masm_, fun->end_position() - 1);
589 }
590 } 592 }
591 593
592 594
593 void FullCodeGenerator::SetStatementPosition(Statement* stmt) { 595 void FullCodeGenerator::SetStatementPosition(Statement* stmt) {
594 if (FLAG_debug_info) {
595 #ifdef ENABLE_DEBUGGER_SUPPORT 596 #ifdef ENABLE_DEBUGGER_SUPPORT
596 if (!isolate()->debugger()->IsDebuggerActive()) { 597 if (!isolate()->debugger()->IsDebuggerActive()) {
597 CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); 598 CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
598 } else { 599 } else {
599 // Check if the statement will be breakable without adding a debug break 600 // Check if the statement will be breakable without adding a debug break
600 // slot. 601 // slot.
601 BreakableStatementChecker checker; 602 BreakableStatementChecker checker;
602 checker.Check(stmt); 603 checker.Check(stmt);
603 // Record the statement position right here if the statement is not 604 // Record the statement position right here if the statement is not
604 // breakable. For breakable statements the actual recording of the 605 // breakable. For breakable statements the actual recording of the
605 // position will be postponed to the breakable code (typically an IC). 606 // position will be postponed to the breakable code (typically an IC).
606 bool position_recorded = CodeGenerator::RecordPositions( 607 bool position_recorded = CodeGenerator::RecordPositions(
607 masm_, stmt->statement_pos(), !checker.is_breakable()); 608 masm_, stmt->statement_pos(), !checker.is_breakable());
608 // If the position recording did record a new position generate a debug 609 // If the position recording did record a new position generate a debug
609 // break slot to make the statement breakable. 610 // break slot to make the statement breakable.
610 if (position_recorded) { 611 if (position_recorded) {
611 Debug::GenerateSlot(masm_); 612 Debug::GenerateSlot(masm_);
612 }
613 } 613 }
614 }
614 #else 615 #else
615 CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); 616 CodeGenerator::RecordPositions(masm_, stmt->statement_pos());
616 #endif 617 #endif
617 }
618 } 618 }
619 619
620 620
621 void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) { 621 void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) {
622 if (FLAG_debug_info) {
623 #ifdef ENABLE_DEBUGGER_SUPPORT 622 #ifdef ENABLE_DEBUGGER_SUPPORT
624 if (!isolate()->debugger()->IsDebuggerActive()) { 623 if (!isolate()->debugger()->IsDebuggerActive()) {
625 CodeGenerator::RecordPositions(masm_, pos); 624 CodeGenerator::RecordPositions(masm_, pos);
626 } else { 625 } else {
627 // Check if the expression will be breakable without adding a debug break 626 // Check if the expression will be breakable without adding a debug break
628 // slot. 627 // slot.
629 BreakableStatementChecker checker; 628 BreakableStatementChecker checker;
630 checker.Check(expr); 629 checker.Check(expr);
631 // Record a statement position right here if the expression is not 630 // Record a statement position right here if the expression is not
632 // breakable. For breakable expressions the actual recording of the 631 // breakable. For breakable expressions the actual recording of the
633 // position will be postponed to the breakable code (typically an IC). 632 // position will be postponed to the breakable code (typically an IC).
634 // NOTE this will record a statement position for something which might 633 // NOTE this will record a statement position for something which might
635 // not be a statement. As stepping in the debugger will only stop at 634 // not be a statement. As stepping in the debugger will only stop at
636 // statement positions this is used for e.g. the condition expression of 635 // statement positions this is used for e.g. the condition expression of
637 // a do while loop. 636 // a do while loop.
638 bool position_recorded = CodeGenerator::RecordPositions( 637 bool position_recorded = CodeGenerator::RecordPositions(
639 masm_, pos, !checker.is_breakable()); 638 masm_, pos, !checker.is_breakable());
640 // If the position recording did record a new position generate a debug 639 // If the position recording did record a new position generate a debug
641 // break slot to make the statement breakable. 640 // break slot to make the statement breakable.
642 if (position_recorded) { 641 if (position_recorded) {
643 Debug::GenerateSlot(masm_); 642 Debug::GenerateSlot(masm_);
644 }
645 } 643 }
644 }
646 #else 645 #else
647 CodeGenerator::RecordPositions(masm_, pos); 646 CodeGenerator::RecordPositions(masm_, pos);
648 #endif 647 #endif
649 }
650 } 648 }
651 649
652 650
653 void FullCodeGenerator::SetStatementPosition(int pos) { 651 void FullCodeGenerator::SetStatementPosition(int pos) {
654 if (FLAG_debug_info) { 652 CodeGenerator::RecordPositions(masm_, pos);
655 CodeGenerator::RecordPositions(masm_, pos);
656 }
657 } 653 }
658 654
659 655
660 void FullCodeGenerator::SetSourcePosition(int pos) { 656 void FullCodeGenerator::SetSourcePosition(int pos) {
661 if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { 657 if (pos != RelocInfo::kNoPosition) {
662 masm_->positions_recorder()->RecordPosition(pos); 658 masm_->positions_recorder()->RecordPosition(pos);
663 } 659 }
664 } 660 }
665 661
666 662
667 // Lookup table for code generators for special runtime calls which are 663 // Lookup table for code generators for special runtime calls which are
668 // generated inline. 664 // generated inline.
669 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 665 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \
670 &FullCodeGenerator::Emit##Name, 666 &FullCodeGenerator::Emit##Name,
671 667
(...skipping 22 matching lines...) Expand all
694 const Runtime::Function* function = node->function(); 690 const Runtime::Function* function = node->function();
695 ASSERT(function != NULL); 691 ASSERT(function != NULL);
696 ASSERT(function->intrinsic_type == Runtime::INLINE); 692 ASSERT(function->intrinsic_type == Runtime::INLINE);
697 InlineFunctionGenerator generator = 693 InlineFunctionGenerator generator =
698 FindInlineFunctionGenerator(function->function_id); 694 FindInlineFunctionGenerator(function->function_id);
699 ((*this).*(generator))(args); 695 ((*this).*(generator))(args);
700 } 696 }
701 697
702 698
703 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 699 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
704 Comment cmnt(masm_, "[ BinaryOperation"); 700 switch (expr->op()) {
705 Token::Value op = expr->op();
706 Expression* left = expr->left();
707 Expression* right = expr->right();
708
709 OverwriteMode mode = NO_OVERWRITE;
710 if (left->ResultOverwriteAllowed()) {
711 mode = OVERWRITE_LEFT;
712 } else if (right->ResultOverwriteAllowed()) {
713 mode = OVERWRITE_RIGHT;
714 }
715
716 switch (op) {
717 case Token::COMMA: 701 case Token::COMMA:
718 VisitForEffect(left); 702 return VisitComma(expr);
719 if (context()->IsTest()) ForwardBailoutToChild(expr);
720 context()->HandleExpression(right);
721 break;
722
723 case Token::OR: 703 case Token::OR:
724 case Token::AND: 704 case Token::AND:
725 EmitLogicalOperation(expr); 705 return VisitLogicalExpression(expr);
726 break;
727
728 case Token::ADD:
729 case Token::SUB:
730 case Token::DIV:
731 case Token::MOD:
732 case Token::MUL:
733 case Token::BIT_OR:
734 case Token::BIT_AND:
735 case Token::BIT_XOR:
736 case Token::SHL:
737 case Token::SHR:
738 case Token::SAR: {
739 // Load both operands.
740 VisitForStackValue(left);
741 VisitForAccumulatorValue(right);
742
743 SetSourcePosition(expr->position());
744 if (ShouldInlineSmiCase(op)) {
745 EmitInlineSmiBinaryOp(expr, op, mode, left, right);
746 } else {
747 EmitBinaryOp(expr, op, mode);
748 }
749 break;
750 }
751
752 default: 706 default:
753 UNREACHABLE(); 707 return VisitArithmeticExpression(expr);
754 } 708 }
755 } 709 }
756 710
757 711
758 void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { 712 void FullCodeGenerator::VisitComma(BinaryOperation* expr) {
759 Label eval_right, done; 713 Comment cmnt(masm_, "[ Comma");
714 VisitForEffect(expr->left());
715 if (context()->IsTest()) ForwardBailoutToChild(expr);
716 VisitInCurrentContext(expr->right());
717 }
760 718
761 context()->EmitLogicalLeft(expr, &eval_right, &done);
762 719
763 PrepareForBailoutForId(expr->RightId(), NO_REGISTERS); 720 void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
764 __ bind(&eval_right); 721 bool is_logical_and = expr->op() == Token::AND;
765 if (context()->IsTest()) ForwardBailoutToChild(expr); 722 Comment cmnt(masm_, is_logical_and ? "[ Logical AND" : "[ Logical OR");
766 context()->HandleExpression(expr->right()); 723 Expression* left = expr->left();
724 Expression* right = expr->right();
725 int right_id = expr->RightId();
726 Label done;
767 727
728 if (context()->IsTest()) {
729 Label eval_right;
730 const TestContext* test = TestContext::cast(context());
731 if (is_logical_and) {
732 VisitForControl(left, &eval_right, test->false_label(), &eval_right);
733 } else {
734 VisitForControl(left, test->true_label(), &eval_right, &eval_right);
735 }
736 PrepareForBailoutForId(right_id, NO_REGISTERS);
737 __ bind(&eval_right);
738 ForwardBailoutToChild(expr);
739
740 } else if (context()->IsAccumulatorValue()) {
741 VisitForAccumulatorValue(left);
742 // We want the value in the accumulator for the test, and on the stack in
743 // case we need it.
744 __ push(result_register());
745 Label discard, restore;
746 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
747 if (is_logical_and) {
748 DoTest(left, &discard, &restore, &restore);
749 } else {
750 DoTest(left, &restore, &discard, &restore);
751 }
752 __ bind(&restore);
753 __ pop(result_register());
754 __ jmp(&done);
755 __ bind(&discard);
756 __ Drop(1);
757 PrepareForBailoutForId(right_id, NO_REGISTERS);
758
759 } else if (context()->IsStackValue()) {
760 VisitForAccumulatorValue(left);
761 // We want the value in the accumulator for the test, and on the stack in
762 // case we need it.
763 __ push(result_register());
764 Label discard;
765 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
766 if (is_logical_and) {
767 DoTest(left, &discard, &done, &discard);
768 } else {
769 DoTest(left, &done, &discard, &discard);
770 }
771 __ bind(&discard);
772 __ Drop(1);
773 PrepareForBailoutForId(right_id, NO_REGISTERS);
774
775 } else {
776 ASSERT(context()->IsEffect());
777 Label eval_right;
778 if (is_logical_and) {
779 VisitForControl(left, &eval_right, &done, &eval_right);
780 } else {
781 VisitForControl(left, &done, &eval_right, &eval_right);
782 }
783 PrepareForBailoutForId(right_id, NO_REGISTERS);
784 __ bind(&eval_right);
785 }
786
787 VisitInCurrentContext(right);
768 __ bind(&done); 788 __ bind(&done);
769 } 789 }
770 790
771 791
772 void FullCodeGenerator::EffectContext::EmitLogicalLeft(BinaryOperation* expr, 792 void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
773 Label* eval_right, 793 Token::Value op = expr->op();
774 Label* done) const { 794 Comment cmnt(masm_, "[ ArithmeticExpression");
775 if (expr->op() == Token::OR) { 795 Expression* left = expr->left();
776 codegen()->VisitForControl(expr->left(), done, eval_right, eval_right); 796 Expression* right = expr->right();
797 OverwriteMode mode =
798 left->ResultOverwriteAllowed()
799 ? OVERWRITE_LEFT
800 : (right->ResultOverwriteAllowed() ? OVERWRITE_RIGHT : NO_OVERWRITE);
801
802 VisitForStackValue(left);
803 VisitForAccumulatorValue(right);
804
805 SetSourcePosition(expr->position());
806 if (ShouldInlineSmiCase(op)) {
807 EmitInlineSmiBinaryOp(expr, op, mode, left, right);
777 } else { 808 } else {
778 ASSERT(expr->op() == Token::AND); 809 EmitBinaryOp(expr, op, mode);
779 codegen()->VisitForControl(expr->left(), eval_right, done, eval_right);
780 } 810 }
781 } 811 }
782 812
783
784 void FullCodeGenerator::AccumulatorValueContext::EmitLogicalLeft(
785 BinaryOperation* expr,
786 Label* eval_right,
787 Label* done) const {
788 HandleExpression(expr->left());
789 // We want the value in the accumulator for the test, and on the stack in case
790 // we need it.
791 __ push(result_register());
792 Label discard, restore;
793 if (expr->op() == Token::OR) {
794 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
795 codegen()->DoTest(&restore, &discard, &restore);
796 } else {
797 ASSERT(expr->op() == Token::AND);
798 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
799 codegen()->DoTest(&discard, &restore, &restore);
800 }
801 __ bind(&restore);
802 __ pop(result_register());
803 __ jmp(done);
804 __ bind(&discard);
805 __ Drop(1);
806 }
807
808
809 void FullCodeGenerator::StackValueContext::EmitLogicalLeft(
810 BinaryOperation* expr,
811 Label* eval_right,
812 Label* done) const {
813 codegen()->VisitForAccumulatorValue(expr->left());
814 // We want the value in the accumulator for the test, and on the stack in case
815 // we need it.
816 __ push(result_register());
817 Label discard;
818 if (expr->op() == Token::OR) {
819 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
820 codegen()->DoTest(done, &discard, &discard);
821 } else {
822 ASSERT(expr->op() == Token::AND);
823 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
824 codegen()->DoTest(&discard, done, &discard);
825 }
826 __ bind(&discard);
827 __ Drop(1);
828 }
829
830
831 void FullCodeGenerator::TestContext::EmitLogicalLeft(BinaryOperation* expr,
832 Label* eval_right,
833 Label* done) const {
834 if (expr->op() == Token::OR) {
835 codegen()->VisitForControl(expr->left(),
836 true_label_, eval_right, eval_right);
837 } else {
838 ASSERT(expr->op() == Token::AND);
839 codegen()->VisitForControl(expr->left(),
840 eval_right, false_label_, eval_right);
841 }
842 }
843
844 813
845 void FullCodeGenerator::ForwardBailoutToChild(Expression* expr) { 814 void FullCodeGenerator::ForwardBailoutToChild(Expression* expr) {
846 if (!info_->HasDeoptimizationSupport()) return; 815 if (!info_->HasDeoptimizationSupport()) return;
847 ASSERT(context()->IsTest()); 816 ASSERT(context()->IsTest());
848 ASSERT(expr == forward_bailout_stack_->expr()); 817 ASSERT(expr == forward_bailout_stack_->expr());
849 forward_bailout_pending_ = forward_bailout_stack_; 818 forward_bailout_pending_ = forward_bailout_stack_;
850 } 819 }
851 820
852 821
853 void FullCodeGenerator::EffectContext::HandleExpression( 822 void FullCodeGenerator::VisitInCurrentContext(Expression* expr) {
854 Expression* expr) const { 823 if (context()->IsTest()) {
855 codegen()->HandleInNonTestContext(expr, NO_REGISTERS); 824 ForwardBailoutStack stack(expr, forward_bailout_pending_);
856 } 825 ForwardBailoutStack* saved = forward_bailout_stack_;
857 826 forward_bailout_pending_ = NULL;
858 827 forward_bailout_stack_ = &stack;
859 void FullCodeGenerator::AccumulatorValueContext::HandleExpression( 828 Visit(expr);
860 Expression* expr) const { 829 forward_bailout_stack_ = saved;
861 codegen()->HandleInNonTestContext(expr, TOS_REG); 830 } else {
862 } 831 ASSERT(forward_bailout_pending_ == NULL);
863 832 Visit(expr);
864 833 State state = context()->IsAccumulatorValue() ? TOS_REG : NO_REGISTERS;
865 void FullCodeGenerator::StackValueContext::HandleExpression( 834 PrepareForBailout(expr, state);
866 Expression* expr) const { 835 // Forwarding bailouts to children is a one shot operation. It should have
867 codegen()->HandleInNonTestContext(expr, NO_REGISTERS); 836 // been processed at this point.
868 } 837 ASSERT(forward_bailout_pending_ == NULL);
869 838 }
870
871 void FullCodeGenerator::TestContext::HandleExpression(Expression* expr) const {
872 codegen()->VisitInTestContext(expr);
873 }
874
875
876 void FullCodeGenerator::HandleInNonTestContext(Expression* expr, State state) {
877 ASSERT(forward_bailout_pending_ == NULL);
878 AstVisitor::Visit(expr);
879 PrepareForBailout(expr, state);
880 // Forwarding bailouts to children is a one shot operation. It
881 // should have been processed at this point.
882 ASSERT(forward_bailout_pending_ == NULL);
883 }
884
885
886 void FullCodeGenerator::VisitInTestContext(Expression* expr) {
887 ForwardBailoutStack stack(expr, forward_bailout_pending_);
888 ForwardBailoutStack* saved = forward_bailout_stack_;
889 forward_bailout_pending_ = NULL;
890 forward_bailout_stack_ = &stack;
891 AstVisitor::Visit(expr);
892 forward_bailout_stack_ = saved;
893 } 839 }
894 840
895 841
896 void FullCodeGenerator::VisitBlock(Block* stmt) { 842 void FullCodeGenerator::VisitBlock(Block* stmt) {
897 Comment cmnt(masm_, "[ Block"); 843 Comment cmnt(masm_, "[ Block");
898 Breakable nested_statement(this, stmt); 844 Breakable nested_statement(this, stmt);
899 SetStatementPosition(stmt); 845 SetStatementPosition(stmt);
900 846
901 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 847 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
902 VisitStatements(stmt->statements()); 848 VisitStatements(stmt->statements());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 Visit(stmt->else_statement()); 881 Visit(stmt->else_statement());
936 } else { 882 } else {
937 VisitForControl(stmt->condition(), &then_part, &done, &then_part); 883 VisitForControl(stmt->condition(), &then_part, &done, &then_part);
938 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS); 884 PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
939 __ bind(&then_part); 885 __ bind(&then_part);
940 Visit(stmt->then_statement()); 886 Visit(stmt->then_statement());
941 887
942 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS); 888 PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
943 } 889 }
944 __ bind(&done); 890 __ bind(&done);
945 PrepareForBailoutForId(stmt->id(), NO_REGISTERS); 891 PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
946 } 892 }
947 893
948 894
949 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { 895 void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
950 Comment cmnt(masm_, "[ ContinueStatement"); 896 Comment cmnt(masm_, "[ ContinueStatement");
951 SetStatementPosition(stmt); 897 SetStatementPosition(stmt);
952 NestedStatement* current = nesting_stack_; 898 NestedStatement* current = nesting_stack_;
953 int stack_depth = 0; 899 int stack_depth = 0;
954 // When continuing, we clobber the unpredictable value in the accumulator 900 // When continuing, we clobber the unpredictable value in the accumulator
955 // with one that's safe for GC. If we hit an exit from the try block of 901 // with one that's safe for GC. If we hit an exit from the try block of
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 while (current != NULL) { 946 while (current != NULL) {
1001 stack_depth = current->Exit(stack_depth); 947 stack_depth = current->Exit(stack_depth);
1002 current = current->outer(); 948 current = current->outer();
1003 } 949 }
1004 __ Drop(stack_depth); 950 __ Drop(stack_depth);
1005 951
1006 EmitReturnSequence(); 952 EmitReturnSequence();
1007 } 953 }
1008 954
1009 955
1010 void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { 956 void FullCodeGenerator::VisitEnterWithContextStatement(
1011 Comment cmnt(masm_, "[ WithEnterStatement"); 957 EnterWithContextStatement* stmt) {
958 Comment cmnt(masm_, "[ EnterWithContextStatement");
1012 SetStatementPosition(stmt); 959 SetStatementPosition(stmt);
1013 960
1014 VisitForStackValue(stmt->expression()); 961 VisitForStackValue(stmt->expression());
1015 if (stmt->is_catch_block()) { 962 PushFunctionArgumentForContextAllocation();
1016 __ CallRuntime(Runtime::kPushCatchContext, 1); 963 __ CallRuntime(Runtime::kPushWithContext, 2);
1017 } else {
1018 __ CallRuntime(Runtime::kPushContext, 1);
1019 }
1020 // Both runtime calls return the new context in both the context and the
1021 // result registers.
1022
1023 // Update local stack frame context field.
1024 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); 964 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1025 } 965 }
1026 966
1027 967
1028 void FullCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) { 968 void FullCodeGenerator::VisitExitContextStatement(ExitContextStatement* stmt) {
1029 Comment cmnt(masm_, "[ WithExitStatement"); 969 Comment cmnt(masm_, "[ ExitContextStatement");
1030 SetStatementPosition(stmt); 970 SetStatementPosition(stmt);
1031 971
1032 // Pop context. 972 // Pop context.
1033 LoadContextField(context_register(), Context::PREVIOUS_INDEX); 973 LoadContextField(context_register(), Context::PREVIOUS_INDEX);
1034 // Update local stack frame context field. 974 // Update local stack frame context field.
1035 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); 975 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
1036 } 976 }
1037 977
1038 978
1039 void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 979 void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 // At this point, the exception is in a register, and store it in 1100 // At this point, the exception is in a register, and store it in
1161 // the temporary local variable (prints as ".catch-var") before 1101 // the temporary local variable (prints as ".catch-var") before
1162 // executing the catch block. The catch block has been rewritten 1102 // executing the catch block. The catch block has been rewritten
1163 // to introduce a new scope to bind the catch variable and to remove 1103 // to introduce a new scope to bind the catch variable and to remove
1164 // that scope again afterwards. 1104 // that scope again afterwards.
1165 1105
1166 Label try_handler_setup, catch_entry, done; 1106 Label try_handler_setup, catch_entry, done;
1167 __ Call(&try_handler_setup); 1107 __ Call(&try_handler_setup);
1168 // Try handler code, exception in result register. 1108 // Try handler code, exception in result register.
1169 1109
1170 // Store exception in local .catch variable before executing catch block. 1110 // Extend the context before executing the catch block.
1171 { 1111 { Comment cmnt(masm_, "[ Extend catch context");
1172 // The catch variable is *always* a variable proxy for a local variable. 1112 __ Push(stmt->variable()->name());
1173 Variable* catch_var = stmt->catch_var()->AsVariableProxy()->AsVariable(); 1113 __ push(result_register());
1174 ASSERT_NOT_NULL(catch_var); 1114 PushFunctionArgumentForContextAllocation();
1175 Slot* variable_slot = catch_var->AsSlot(); 1115 __ CallRuntime(Runtime::kPushCatchContext, 3);
1176 ASSERT_NOT_NULL(variable_slot); 1116 StoreToFrameField(StandardFrameConstants::kContextOffset,
1177 ASSERT_EQ(Slot::LOCAL, variable_slot->type()); 1117 context_register());
1178 StoreToFrameField(SlotOffset(variable_slot), result_register());
1179 } 1118 }
1180 1119
1120 Scope* saved_scope = scope();
1121 scope_ = stmt->scope();
1122 ASSERT(scope_->declarations()->is_empty());
1181 Visit(stmt->catch_block()); 1123 Visit(stmt->catch_block());
1124 scope_ = saved_scope;
1182 __ jmp(&done); 1125 __ jmp(&done);
1183 1126
1184 // Try block code. Sets up the exception handler chain. 1127 // Try block code. Sets up the exception handler chain.
1185 __ bind(&try_handler_setup); 1128 __ bind(&try_handler_setup);
1186 { 1129 {
1187 TryCatch try_block(this, &catch_entry); 1130 TryCatch try_block(this, &catch_entry);
1188 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER); 1131 __ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
1189 Visit(stmt->try_block()); 1132 Visit(stmt->try_block());
1190 __ PopTryHandler(); 1133 __ PopTryHandler();
1191 } 1134 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1280 __ bind(&true_case); 1223 __ bind(&true_case);
1281 SetExpressionPosition(expr->then_expression(), 1224 SetExpressionPosition(expr->then_expression(),
1282 expr->then_expression_position()); 1225 expr->then_expression_position());
1283 if (context()->IsTest()) { 1226 if (context()->IsTest()) {
1284 const TestContext* for_test = TestContext::cast(context()); 1227 const TestContext* for_test = TestContext::cast(context());
1285 VisitForControl(expr->then_expression(), 1228 VisitForControl(expr->then_expression(),
1286 for_test->true_label(), 1229 for_test->true_label(),
1287 for_test->false_label(), 1230 for_test->false_label(),
1288 NULL); 1231 NULL);
1289 } else { 1232 } else {
1290 context()->HandleExpression(expr->then_expression()); 1233 VisitInCurrentContext(expr->then_expression());
1291 __ jmp(&done); 1234 __ jmp(&done);
1292 } 1235 }
1293 1236
1294 PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS); 1237 PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
1295 __ bind(&false_case); 1238 __ bind(&false_case);
1296 if (context()->IsTest()) ForwardBailoutToChild(expr); 1239 if (context()->IsTest()) ForwardBailoutToChild(expr);
1297 SetExpressionPosition(expr->else_expression(), 1240 SetExpressionPosition(expr->else_expression(),
1298 expr->else_expression_position()); 1241 expr->else_expression_position());
1299 context()->HandleExpression(expr->else_expression()); 1242 VisitInCurrentContext(expr->else_expression());
1300 // If control flow falls through Visit, merge it with true case here. 1243 // If control flow falls through Visit, merge it with true case here.
1301 if (!context()->IsTest()) { 1244 if (!context()->IsTest()) {
1302 __ bind(&done); 1245 __ bind(&done);
1303 } 1246 }
1304 } 1247 }
1305 1248
1306 1249
1307 void FullCodeGenerator::VisitLiteral(Literal* expr) { 1250 void FullCodeGenerator::VisitLiteral(Literal* expr) {
1308 Comment cmnt(masm_, "[ Literal"); 1251 Comment cmnt(masm_, "[ Literal");
1309 context()->Plug(expr->handle()); 1252 context()->Plug(expr->handle());
(...skipping 14 matching lines...) Expand all
1324 } 1267 }
1325 1268
1326 1269
1327 void FullCodeGenerator::VisitSharedFunctionInfoLiteral( 1270 void FullCodeGenerator::VisitSharedFunctionInfoLiteral(
1328 SharedFunctionInfoLiteral* expr) { 1271 SharedFunctionInfoLiteral* expr) {
1329 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral"); 1272 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
1330 EmitNewClosure(expr->shared_function_info(), false); 1273 EmitNewClosure(expr->shared_function_info(), false);
1331 } 1274 }
1332 1275
1333 1276
1334 void FullCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
1335 // Call runtime routine to allocate the catch extension object and
1336 // assign the exception value to the catch variable.
1337 Comment cmnt(masm_, "[ CatchExtensionObject");
1338 VisitForStackValue(expr->key());
1339 VisitForStackValue(expr->value());
1340 // Create catch extension object.
1341 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
1342 context()->Plug(result_register());
1343 }
1344
1345
1346 void FullCodeGenerator::VisitThrow(Throw* expr) { 1277 void FullCodeGenerator::VisitThrow(Throw* expr) {
1347 Comment cmnt(masm_, "[ Throw"); 1278 Comment cmnt(masm_, "[ Throw");
1348 VisitForStackValue(expr->exception()); 1279 VisitForStackValue(expr->exception());
1349 __ CallRuntime(Runtime::kThrow, 1); 1280 __ CallRuntime(Runtime::kThrow, 1);
1350 // Never returns here. 1281 // Never returns here.
1351 } 1282 }
1352 1283
1353 1284
1354 int FullCodeGenerator::TryFinally::Exit(int stack_depth) { 1285 int FullCodeGenerator::TryFinally::Exit(int stack_depth) {
1355 // The macros used here must preserve the result register. 1286 // The macros used here must preserve the result register.
1356 __ Drop(stack_depth); 1287 __ Drop(stack_depth);
1357 __ PopTryHandler(); 1288 __ PopTryHandler();
1358 __ Call(finally_entry_); 1289 __ Call(finally_entry_);
1359 return 0; 1290 return 0;
1360 } 1291 }
1361 1292
1362 1293
1363 int FullCodeGenerator::TryCatch::Exit(int stack_depth) { 1294 int FullCodeGenerator::TryCatch::Exit(int stack_depth) {
1364 // The macros used here must preserve the result register. 1295 // The macros used here must preserve the result register.
1365 __ Drop(stack_depth); 1296 __ Drop(stack_depth);
1366 __ PopTryHandler(); 1297 __ PopTryHandler();
1367 return 0; 1298 return 0;
1368 } 1299 }
1369 1300
1370 1301
1302 bool FullCodeGenerator::TryLiteralCompare(CompareOperation* compare,
1303 Label* if_true,
1304 Label* if_false,
1305 Label* fall_through) {
1306 Expression *expr;
1307 Handle<String> check;
1308 if (compare->IsLiteralCompareTypeof(&expr, &check)) {
1309 EmitLiteralCompareTypeof(expr, check, if_true, if_false, fall_through);
1310 return true;
1311 }
1312
1313 if (compare->IsLiteralCompareUndefined(&expr)) {
1314 EmitLiteralCompareUndefined(expr, if_true, if_false, fall_through);
1315 return true;
1316 }
1317
1318 return false;
1319 }
1320
1321
1371 #undef __ 1322 #undef __
1372 1323
1373 1324
1374 } } // namespace v8::internal 1325 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/full-codegen.h ('k') | src/func-name-inferrer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698