OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 offset += JavaScriptFrameConstants::kLocal0Offset; | 68 offset += JavaScriptFrameConstants::kLocal0Offset; |
69 break; | 69 break; |
70 case Slot::CONTEXT: | 70 case Slot::CONTEXT: |
71 case Slot::LOOKUP: | 71 case Slot::LOOKUP: |
72 UNREACHABLE(); | 72 UNREACHABLE(); |
73 } | 73 } |
74 return offset; | 74 return offset; |
75 } | 75 } |
76 | 76 |
77 | 77 |
78 void FastCodeGenerator::Apply(Expression::Context context, Register reg) { | |
79 switch (context) { | |
80 case Expression::kUninitialized: | |
81 UNREACHABLE(); | |
82 case Expression::kEffect: | |
83 break; | |
84 case Expression::kValue: | |
85 __ push(reg); | |
86 break; | |
87 case Expression::kTest: | |
88 TestAndBranch(reg, true_label_, false_label_); | |
89 break; | |
90 case Expression::kValueTest: { | |
91 Label discard; | |
92 __ push(reg); | |
93 TestAndBranch(reg, true_label_, &discard); | |
94 __ bind(&discard); | |
95 __ Drop(1); | |
96 __ jmp(false_label_); | |
97 break; | |
98 } | |
99 case Expression::kTestValue: { | |
100 Label discard; | |
101 __ push(reg); | |
102 TestAndBranch(reg, &discard, false_label_); | |
103 __ bind(&discard); | |
104 __ Drop(1); | |
105 __ jmp(true_label_); | |
106 } | |
107 } | |
108 } | |
109 | |
110 | |
111 void FastCodeGenerator::VisitDeclarations( | 78 void FastCodeGenerator::VisitDeclarations( |
112 ZoneList<Declaration*>* declarations) { | 79 ZoneList<Declaration*>* declarations) { |
113 int length = declarations->length(); | 80 int length = declarations->length(); |
114 int globals = 0; | 81 int globals = 0; |
115 for (int i = 0; i < length; i++) { | 82 for (int i = 0; i < length; i++) { |
116 Declaration* decl = declarations->at(i); | 83 Declaration* decl = declarations->at(i); |
117 Variable* var = decl->proxy()->var(); | 84 Variable* var = decl->proxy()->var(); |
118 Slot* slot = var->slot(); | 85 Slot* slot = var->slot(); |
119 | 86 |
120 // If it was not possible to allocate the variable at compile | 87 // If it was not possible to allocate the variable at compile |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 } | 143 } |
177 | 144 |
178 | 145 |
179 void FastCodeGenerator::SetStatementPosition(Statement* stmt) { | 146 void FastCodeGenerator::SetStatementPosition(Statement* stmt) { |
180 if (FLAG_debug_info) { | 147 if (FLAG_debug_info) { |
181 CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); | 148 CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); |
182 } | 149 } |
183 } | 150 } |
184 | 151 |
185 | 152 |
| 153 void FastCodeGenerator::SetStatementPosition(int pos) { |
| 154 if (FLAG_debug_info) { |
| 155 CodeGenerator::RecordPositions(masm_, pos); |
| 156 } |
| 157 } |
| 158 |
| 159 |
186 void FastCodeGenerator::SetSourcePosition(int pos) { | 160 void FastCodeGenerator::SetSourcePosition(int pos) { |
187 if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { | 161 if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { |
188 masm_->RecordPosition(pos); | 162 masm_->RecordPosition(pos); |
189 } | 163 } |
190 } | 164 } |
191 | 165 |
192 | 166 |
193 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { | 167 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { |
194 #ifdef DEBUG | 168 #ifdef DEBUG |
195 Expression::Context expected = Expression::kUninitialized; | 169 Expression::Context expected = Expression::kUninitialized; |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 | 305 |
332 Breakable* target = current->AsBreakable(); | 306 Breakable* target = current->AsBreakable(); |
333 __ jmp(target->break_target()); | 307 __ jmp(target->break_target()); |
334 } | 308 } |
335 | 309 |
336 | 310 |
337 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 311 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
338 Comment cmnt(masm_, "[ ReturnStatement"); | 312 Comment cmnt(masm_, "[ ReturnStatement"); |
339 SetStatementPosition(stmt); | 313 SetStatementPosition(stmt); |
340 Expression* expr = stmt->expression(); | 314 Expression* expr = stmt->expression(); |
341 // Complete the statement based on the type of the subexpression. | 315 VisitForValue(expr, kAccumulator); |
342 if (expr->AsLiteral() != NULL) { | |
343 __ Move(result_register(), expr->AsLiteral()->handle()); | |
344 } else { | |
345 ASSERT_EQ(Expression::kValue, expr->context()); | |
346 Visit(expr); | |
347 __ pop(result_register()); | |
348 } | |
349 | 316 |
350 // Exit all nested statements. | 317 // Exit all nested statements. |
351 NestedStatement* current = nesting_stack_; | 318 NestedStatement* current = nesting_stack_; |
352 int stack_depth = 0; | 319 int stack_depth = 0; |
353 while (current != NULL) { | 320 while (current != NULL) { |
354 stack_depth = current->Exit(stack_depth); | 321 stack_depth = current->Exit(stack_depth); |
355 current = current->outer(); | 322 current = current->outer(); |
356 } | 323 } |
357 __ Drop(stack_depth); | 324 __ Drop(stack_depth); |
358 | 325 |
359 EmitReturnSequence(stmt->statement_pos()); | 326 EmitReturnSequence(stmt->statement_pos()); |
360 } | 327 } |
361 | 328 |
362 | 329 |
363 | |
364 | |
365 void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { | 330 void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { |
366 Comment cmnt(masm_, "[ WithEnterStatement"); | 331 Comment cmnt(masm_, "[ WithEnterStatement"); |
367 SetStatementPosition(stmt); | 332 SetStatementPosition(stmt); |
368 | 333 |
369 Visit(stmt->expression()); | 334 VisitForValue(stmt->expression(), kStack); |
370 if (stmt->is_catch_block()) { | 335 if (stmt->is_catch_block()) { |
371 __ CallRuntime(Runtime::kPushCatchContext, 1); | 336 __ CallRuntime(Runtime::kPushCatchContext, 1); |
372 } else { | 337 } else { |
373 __ CallRuntime(Runtime::kPushContext, 1); | 338 __ CallRuntime(Runtime::kPushContext, 1); |
374 } | 339 } |
375 // Both runtime calls return the new context in both the context and the | 340 // Both runtime calls return the new context in both the context and the |
376 // result registers. | 341 // result registers. |
377 | 342 |
378 // Update local stack frame context field. | 343 // Update local stack frame context field. |
379 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); | 344 StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); |
(...skipping 25 matching lines...) Expand all Loading... |
405 increment_loop_depth(); | 370 increment_loop_depth(); |
406 | 371 |
407 __ bind(&body); | 372 __ bind(&body); |
408 Visit(stmt->body()); | 373 Visit(stmt->body()); |
409 | 374 |
410 // Check stack before looping. | 375 // Check stack before looping. |
411 __ StackLimitCheck(&stack_limit_hit); | 376 __ StackLimitCheck(&stack_limit_hit); |
412 __ bind(&stack_check_success); | 377 __ bind(&stack_check_success); |
413 | 378 |
414 __ bind(loop_statement.continue_target()); | 379 __ bind(loop_statement.continue_target()); |
| 380 SetStatementPosition(stmt->condition_position()); |
415 VisitForControl(stmt->cond(), &body, loop_statement.break_target()); | 381 VisitForControl(stmt->cond(), &body, loop_statement.break_target()); |
416 | 382 |
417 __ bind(&stack_limit_hit); | 383 __ bind(&stack_limit_hit); |
418 StackCheckStub stack_stub; | 384 StackCheckStub stack_stub; |
419 __ CallStub(&stack_stub); | 385 __ CallStub(&stack_stub); |
420 __ jmp(&stack_check_success); | 386 __ jmp(&stack_check_success); |
421 | 387 |
422 __ bind(loop_statement.break_target()); | 388 __ bind(loop_statement.break_target()); |
423 | 389 |
424 decrement_loop_depth(); | 390 decrement_loop_depth(); |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 | 592 |
627 void FastCodeGenerator::VisitLiteral(Literal* expr) { | 593 void FastCodeGenerator::VisitLiteral(Literal* expr) { |
628 Comment cmnt(masm_, "[ Literal"); | 594 Comment cmnt(masm_, "[ Literal"); |
629 Apply(expr->context(), expr); | 595 Apply(expr->context(), expr); |
630 } | 596 } |
631 | 597 |
632 | 598 |
633 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 599 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
634 Comment cmnt(masm_, "[ Assignment"); | 600 Comment cmnt(masm_, "[ Assignment"); |
635 | 601 |
636 // Record source code position of the (possible) IC call. | |
637 SetSourcePosition(expr->position()); | |
638 | |
639 // Left-hand side can only be a property, a global or a (parameter or local) | 602 // Left-hand side can only be a property, a global or a (parameter or local) |
640 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 603 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
641 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 604 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
642 LhsKind assign_type = VARIABLE; | 605 LhsKind assign_type = VARIABLE; |
643 Property* prop = expr->target()->AsProperty(); | 606 Property* prop = expr->target()->AsProperty(); |
644 // In case of a property we use the uninitialized expression context | 607 // In case of a property we use the uninitialized expression context |
645 // of the key to detect a named property. | 608 // of the key to detect a named property. |
646 if (prop != NULL) { | 609 if (prop != NULL) { |
647 assign_type = (prop->key()->context() == Expression::kUninitialized) | 610 assign_type = (prop->key()->context() == Expression::kUninitialized) |
648 ? NAMED_PROPERTY | 611 ? NAMED_PROPERTY |
649 : KEYED_PROPERTY; | 612 : KEYED_PROPERTY; |
650 } | 613 } |
651 | 614 |
652 // Evaluate LHS expression. | 615 // Evaluate LHS expression. |
653 switch (assign_type) { | 616 switch (assign_type) { |
654 case VARIABLE: | 617 case VARIABLE: |
655 // Nothing to do here. | 618 // Nothing to do here. |
656 break; | 619 break; |
657 case NAMED_PROPERTY: | 620 case NAMED_PROPERTY: |
658 Visit(prop->obj()); | 621 VisitForValue(prop->obj(), kStack); |
659 ASSERT_EQ(Expression::kValue, prop->obj()->context()); | |
660 break; | 622 break; |
661 case KEYED_PROPERTY: | 623 case KEYED_PROPERTY: |
662 Visit(prop->obj()); | 624 VisitForValue(prop->obj(), kStack); |
663 ASSERT_EQ(Expression::kValue, prop->obj()->context()); | 625 VisitForValue(prop->key(), kStack); |
664 Visit(prop->key()); | |
665 ASSERT_EQ(Expression::kValue, prop->key()->context()); | |
666 break; | 626 break; |
667 } | 627 } |
668 | 628 |
669 // If we have a compound assignment: Get value of LHS expression and | 629 // If we have a compound assignment: Get value of LHS expression and |
670 // store in on top of the stack. | 630 // store in on top of the stack. |
671 // Note: Relies on kValue context being 'stack'. | |
672 if (expr->is_compound()) { | 631 if (expr->is_compound()) { |
| 632 Location saved_location = location_; |
| 633 location_ = kStack; |
673 switch (assign_type) { | 634 switch (assign_type) { |
674 case VARIABLE: | 635 case VARIABLE: |
675 EmitVariableLoad(expr->target()->AsVariableProxy()->var(), | 636 EmitVariableLoad(expr->target()->AsVariableProxy()->var(), |
676 Expression::kValue); | 637 Expression::kValue); |
677 break; | 638 break; |
678 case NAMED_PROPERTY: | 639 case NAMED_PROPERTY: |
679 EmitNamedPropertyLoad(prop, Expression::kValue); | 640 EmitNamedPropertyLoad(prop); |
| 641 __ push(result_register()); |
680 break; | 642 break; |
681 case KEYED_PROPERTY: | 643 case KEYED_PROPERTY: |
682 EmitKeyedPropertyLoad(prop, Expression::kValue); | 644 EmitKeyedPropertyLoad(prop); |
| 645 __ push(result_register()); |
683 break; | 646 break; |
684 } | 647 } |
| 648 location_ = saved_location; |
685 } | 649 } |
686 | 650 |
687 // Evaluate RHS expression. | 651 // Evaluate RHS expression. |
688 Expression* rhs = expr->value(); | 652 Expression* rhs = expr->value(); |
689 ASSERT_EQ(Expression::kValue, rhs->context()); | 653 VisitForValue(rhs, kAccumulator); |
690 Visit(rhs); | |
691 | 654 |
692 // If we have a compount assignment: Apply operator. | 655 // If we have a compount assignment: Apply operator. |
693 if (expr->is_compound()) { | 656 if (expr->is_compound()) { |
694 EmitCompoundAssignmentOp(expr->binary_op(), Expression::kValue); | 657 Location saved_location = location_; |
| 658 location_ = kAccumulator; |
| 659 EmitBinaryOp(expr->binary_op(), Expression::kValue); |
| 660 location_ = saved_location; |
695 } | 661 } |
696 | 662 |
| 663 // Record source position before possible IC call. |
| 664 SetSourcePosition(expr->position()); |
| 665 |
697 // Store the value. | 666 // Store the value. |
698 switch (assign_type) { | 667 switch (assign_type) { |
699 case VARIABLE: | 668 case VARIABLE: |
700 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 669 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
701 expr->context()); | 670 expr->context()); |
702 break; | 671 break; |
703 case NAMED_PROPERTY: | 672 case NAMED_PROPERTY: |
704 EmitNamedPropertyAssignment(expr); | 673 EmitNamedPropertyAssignment(expr); |
705 break; | 674 break; |
706 case KEYED_PROPERTY: | 675 case KEYED_PROPERTY: |
707 EmitKeyedPropertyAssignment(expr); | 676 EmitKeyedPropertyAssignment(expr); |
708 break; | 677 break; |
709 } | 678 } |
710 } | 679 } |
711 | 680 |
712 | 681 |
713 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 682 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
714 // Call runtime routine to allocate the catch extension object and | 683 // Call runtime routine to allocate the catch extension object and |
715 // assign the exception value to the catch variable. | 684 // assign the exception value to the catch variable. |
716 Comment cmnt(masm_, "[ CatchExtensionObject"); | 685 Comment cmnt(masm_, "[ CatchExtensionObject"); |
717 | 686 |
718 // Push key string. | 687 VisitForValue(expr->key(), kStack); |
719 ASSERT_EQ(Expression::kValue, expr->key()->context()); | 688 VisitForValue(expr->value(), kStack); |
720 Visit(expr->key()); | |
721 ASSERT_EQ(Expression::kValue, expr->value()->context()); | |
722 Visit(expr->value()); | |
723 | 689 |
724 // Create catch extension object. | 690 // Create catch extension object. |
725 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); | 691 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); |
726 | 692 |
727 __ push(result_register()); | 693 __ push(result_register()); |
728 } | 694 } |
729 | 695 |
730 | 696 |
731 void FastCodeGenerator::VisitThrow(Throw* expr) { | 697 void FastCodeGenerator::VisitThrow(Throw* expr) { |
732 Comment cmnt(masm_, "[ Throw"); | 698 Comment cmnt(masm_, "[ Throw"); |
733 Visit(expr->exception()); | 699 VisitForValue(expr->exception(), kStack); |
734 // Exception is on stack. | |
735 __ CallRuntime(Runtime::kThrow, 1); | 700 __ CallRuntime(Runtime::kThrow, 1); |
736 // Never returns here. | 701 // Never returns here. |
737 } | 702 } |
738 | 703 |
739 | 704 |
740 int FastCodeGenerator::TryFinally::Exit(int stack_depth) { | 705 int FastCodeGenerator::TryFinally::Exit(int stack_depth) { |
741 // The macros used here must preserve the result register. | 706 // The macros used here must preserve the result register. |
742 __ Drop(stack_depth); | 707 __ Drop(stack_depth); |
743 __ PopTryHandler(); | 708 __ PopTryHandler(); |
744 __ Call(finally_entry_); | 709 __ Call(finally_entry_); |
745 return 0; | 710 return 0; |
746 } | 711 } |
747 | 712 |
748 | 713 |
749 int FastCodeGenerator::TryCatch::Exit(int stack_depth) { | 714 int FastCodeGenerator::TryCatch::Exit(int stack_depth) { |
750 // The macros used here must preserve the result register. | 715 // The macros used here must preserve the result register. |
751 __ Drop(stack_depth); | 716 __ Drop(stack_depth); |
752 __ PopTryHandler(); | 717 __ PopTryHandler(); |
753 return 0; | 718 return 0; |
754 } | 719 } |
755 | 720 |
756 | 721 |
757 #undef __ | 722 #undef __ |
758 | 723 |
759 | 724 |
760 } } // namespace v8::internal | 725 } } // namespace v8::internal |
OLD | NEW |