| 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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 | 158 |
| 159 | 159 |
| 160 void FastCodeGenerator::SetSourcePosition(int pos) { | 160 void FastCodeGenerator::SetSourcePosition(int pos) { |
| 161 if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { | 161 if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { |
| 162 masm_->RecordPosition(pos); | 162 masm_->RecordPosition(pos); |
| 163 } | 163 } |
| 164 } | 164 } |
| 165 | 165 |
| 166 | 166 |
| 167 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { | 167 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { |
| 168 #ifdef DEBUG | |
| 169 Expression::Context expected = Expression::kUninitialized; | |
| 170 switch (expr->context()) { | |
| 171 case Expression::kUninitialized: | |
| 172 UNREACHABLE(); | |
| 173 case Expression::kEffect: | |
| 174 case Expression::kTest: | |
| 175 // The value of the left subexpression is not needed. | |
| 176 expected = Expression::kTest; | |
| 177 break; | |
| 178 case Expression::kValue: | |
| 179 // The value of the left subexpression is needed and its specific | |
| 180 // context depends on the operator. | |
| 181 expected = (expr->op() == Token::OR) | |
| 182 ? Expression::kValueTest | |
| 183 : Expression::kTestValue; | |
| 184 break; | |
| 185 case Expression::kValueTest: | |
| 186 // The value of the left subexpression is needed for OR. | |
| 187 expected = (expr->op() == Token::OR) | |
| 188 ? Expression::kValueTest | |
| 189 : Expression::kTest; | |
| 190 break; | |
| 191 case Expression::kTestValue: | |
| 192 // The value of the left subexpression is needed for AND. | |
| 193 expected = (expr->op() == Token::OR) | |
| 194 ? Expression::kTest | |
| 195 : Expression::kTestValue; | |
| 196 break; | |
| 197 } | |
| 198 ASSERT_EQ(expected, expr->left()->context()); | |
| 199 ASSERT_EQ(expr->context(), expr->right()->context()); | |
| 200 #endif | |
| 201 | |
| 202 Label eval_right, done; | 168 Label eval_right, done; |
| 203 | 169 |
| 204 // Set up the appropriate context for the left subexpression based | 170 // Set up the appropriate context for the left subexpression based |
| 205 // on the operation and our own context. Initially assume we can | 171 // on the operation and our own context. Initially assume we can |
| 206 // inherit both true and false labels from our context. | 172 // inherit both true and false labels from our context. |
| 207 Label* if_true = true_label_; | |
| 208 Label* if_false = false_label_; | |
| 209 if (expr->op() == Token::OR) { | 173 if (expr->op() == Token::OR) { |
| 210 // If we are not in some kind of a test context, we did not inherit a | 174 switch (context_) { |
| 211 // true label from our context. Use the end of the expression. | 175 case Expression::kUninitialized: |
| 212 if (expr->context() == Expression::kEffect || | 176 UNREACHABLE(); |
| 213 expr->context() == Expression::kValue) { | 177 case Expression::kEffect: |
| 214 if_true = &done; | 178 VisitForControl(expr->left(), &done, &eval_right); |
| 179 break; |
| 180 case Expression::kValue: |
| 181 VisitForValueControl(expr->left(), |
| 182 location_, |
| 183 &done, |
| 184 &eval_right); |
| 185 break; |
| 186 case Expression::kTest: |
| 187 VisitForControl(expr->left(), true_label_, &eval_right); |
| 188 break; |
| 189 case Expression::kValueTest: |
| 190 VisitForValueControl(expr->left(), |
| 191 location_, |
| 192 true_label_, |
| 193 &eval_right); |
| 194 break; |
| 195 case Expression::kTestValue: |
| 196 VisitForControl(expr->left(), true_label_, &eval_right); |
| 197 break; |
| 215 } | 198 } |
| 216 // The false label is the label of the right subexpression. | |
| 217 if_false = &eval_right; | |
| 218 } else { | 199 } else { |
| 219 ASSERT_EQ(Token::AND, expr->op()); | 200 ASSERT_EQ(Token::AND, expr->op()); |
| 220 // The true label is the label of the right subexpression. | 201 switch (context_) { |
| 221 if_true = &eval_right; | 202 case Expression::kUninitialized: |
| 222 // If we are not in some kind of a test context, we did not inherit a | 203 UNREACHABLE(); |
| 223 // false label from our context. Use the end of the expression. | 204 case Expression::kEffect: |
| 224 if (expr->context() == Expression::kEffect || | 205 VisitForControl(expr->left(), &eval_right, &done); |
| 225 expr->context() == Expression::kValue) { | 206 break; |
| 226 if_false = &done; | 207 case Expression::kValue: |
| 208 VisitForControlValue(expr->left(), |
| 209 location_, |
| 210 &eval_right, |
| 211 &done); |
| 212 break; |
| 213 case Expression::kTest: |
| 214 VisitForControl(expr->left(), &eval_right, false_label_); |
| 215 break; |
| 216 case Expression::kValueTest: |
| 217 VisitForControl(expr->left(), &eval_right, false_label_); |
| 218 break; |
| 219 case Expression::kTestValue: |
| 220 VisitForControlValue(expr->left(), |
| 221 location_, |
| 222 &eval_right, |
| 223 false_label_); |
| 224 break; |
| 227 } | 225 } |
| 228 } | 226 } |
| 229 VisitForControl(expr->left(), if_true, if_false); | |
| 230 | 227 |
| 231 __ bind(&eval_right); | 228 __ bind(&eval_right); |
| 232 Visit(expr->right()); | 229 Visit(expr->right()); |
| 233 | 230 |
| 234 __ bind(&done); | 231 __ bind(&done); |
| 235 } | 232 } |
| 236 | 233 |
| 237 | 234 |
| 238 void FastCodeGenerator::VisitBlock(Block* stmt) { | 235 void FastCodeGenerator::VisitBlock(Block* stmt) { |
| 239 Comment cmnt(masm_, "[ Block"); | 236 Comment cmnt(masm_, "[ Block"); |
| 240 Breakable nested_statement(this, stmt); | 237 Breakable nested_statement(this, stmt); |
| 241 SetStatementPosition(stmt); | 238 SetStatementPosition(stmt); |
| 242 VisitStatements(stmt->statements()); | 239 VisitStatements(stmt->statements()); |
| 243 __ bind(nested_statement.break_target()); | 240 __ bind(nested_statement.break_target()); |
| 244 } | 241 } |
| 245 | 242 |
| 246 | 243 |
| 247 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 244 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 248 Comment cmnt(masm_, "[ ExpressionStatement"); | 245 Comment cmnt(masm_, "[ ExpressionStatement"); |
| 249 SetStatementPosition(stmt); | 246 SetStatementPosition(stmt); |
| 250 Visit(stmt->expression()); | 247 VisitForEffect(stmt->expression()); |
| 251 } | 248 } |
| 252 | 249 |
| 253 | 250 |
| 254 void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 251 void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
| 255 Comment cmnt(masm_, "[ EmptyStatement"); | 252 Comment cmnt(masm_, "[ EmptyStatement"); |
| 256 SetStatementPosition(stmt); | 253 SetStatementPosition(stmt); |
| 257 } | 254 } |
| 258 | 255 |
| 259 | 256 |
| 260 void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) { | 257 void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) { |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 // before entering, and removes it again when exiting normally. | 436 // before entering, and removes it again when exiting normally. |
| 440 // If an exception is thrown during execution of the try block, | 437 // If an exception is thrown during execution of the try block, |
| 441 // control is passed to the handler, which also consumes the handler. | 438 // control is passed to the handler, which also consumes the handler. |
| 442 // At this point, the exception is in a register, and store it in | 439 // At this point, the exception is in a register, and store it in |
| 443 // the temporary local variable (prints as ".catch-var") before | 440 // the temporary local variable (prints as ".catch-var") before |
| 444 // executing the catch block. The catch block has been rewritten | 441 // executing the catch block. The catch block has been rewritten |
| 445 // to introduce a new scope to bind the catch variable and to remove | 442 // to introduce a new scope to bind the catch variable and to remove |
| 446 // that scope again afterwards. | 443 // that scope again afterwards. |
| 447 | 444 |
| 448 Label try_handler_setup, catch_entry, done; | 445 Label try_handler_setup, catch_entry, done; |
| 449 | |
| 450 __ Call(&try_handler_setup); | 446 __ Call(&try_handler_setup); |
| 451 // Try handler code, exception in result register. | 447 // Try handler code, exception in result register. |
| 452 | 448 |
| 453 // Store exception in local .catch variable before executing catch block. | 449 // Store exception in local .catch variable before executing catch block. |
| 454 { | 450 { |
| 455 // The catch variable is *always* a variable proxy for a local variable. | 451 // The catch variable is *always* a variable proxy for a local variable. |
| 456 Variable* catch_var = stmt->catch_var()->AsVariableProxy()->AsVariable(); | 452 Variable* catch_var = stmt->catch_var()->AsVariableProxy()->AsVariable(); |
| 457 ASSERT_NOT_NULL(catch_var); | 453 ASSERT_NOT_NULL(catch_var); |
| 458 Slot* variable_slot = catch_var->slot(); | 454 Slot* variable_slot = catch_var->slot(); |
| 459 ASSERT_NOT_NULL(variable_slot); | 455 ASSERT_NOT_NULL(variable_slot); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 | 547 |
| 552 | 548 |
| 553 void FastCodeGenerator::VisitFunctionBoilerplateLiteral( | 549 void FastCodeGenerator::VisitFunctionBoilerplateLiteral( |
| 554 FunctionBoilerplateLiteral* expr) { | 550 FunctionBoilerplateLiteral* expr) { |
| 555 UNREACHABLE(); | 551 UNREACHABLE(); |
| 556 } | 552 } |
| 557 | 553 |
| 558 | 554 |
| 559 void FastCodeGenerator::VisitConditional(Conditional* expr) { | 555 void FastCodeGenerator::VisitConditional(Conditional* expr) { |
| 560 Comment cmnt(masm_, "[ Conditional"); | 556 Comment cmnt(masm_, "[ Conditional"); |
| 561 ASSERT_EQ(Expression::kTest, expr->condition()->context()); | |
| 562 ASSERT_EQ(expr->context(), expr->then_expression()->context()); | |
| 563 ASSERT_EQ(expr->context(), expr->else_expression()->context()); | |
| 564 | |
| 565 | |
| 566 Label true_case, false_case, done; | 557 Label true_case, false_case, done; |
| 567 VisitForControl(expr->condition(), &true_case, &false_case); | 558 VisitForControl(expr->condition(), &true_case, &false_case); |
| 568 | 559 |
| 569 __ bind(&true_case); | 560 __ bind(&true_case); |
| 570 Visit(expr->then_expression()); | 561 Visit(expr->then_expression()); |
| 571 // If control flow falls through Visit, jump to done. | 562 // If control flow falls through Visit, jump to done. |
| 572 if (expr->context() == Expression::kEffect || | 563 if (context_ == Expression::kEffect || context_ == Expression::kValue) { |
| 573 expr->context() == Expression::kValue) { | |
| 574 __ jmp(&done); | 564 __ jmp(&done); |
| 575 } | 565 } |
| 576 | 566 |
| 577 __ bind(&false_case); | 567 __ bind(&false_case); |
| 578 Visit(expr->else_expression()); | 568 Visit(expr->else_expression()); |
| 579 // If control flow falls through Visit, merge it with true case here. | 569 // If control flow falls through Visit, merge it with true case here. |
| 580 if (expr->context() == Expression::kEffect || | 570 if (context_ == Expression::kEffect || context_ == Expression::kValue) { |
| 581 expr->context() == Expression::kValue) { | |
| 582 __ bind(&done); | 571 __ bind(&done); |
| 583 } | 572 } |
| 584 } | 573 } |
| 585 | 574 |
| 586 | 575 |
| 587 void FastCodeGenerator::VisitSlot(Slot* expr) { | 576 void FastCodeGenerator::VisitSlot(Slot* expr) { |
| 588 // Slots do not appear directly in the AST. | 577 // Slots do not appear directly in the AST. |
| 589 UNREACHABLE(); | 578 UNREACHABLE(); |
| 590 } | 579 } |
| 591 | 580 |
| 592 | 581 |
| 593 void FastCodeGenerator::VisitLiteral(Literal* expr) { | 582 void FastCodeGenerator::VisitLiteral(Literal* expr) { |
| 594 Comment cmnt(masm_, "[ Literal"); | 583 Comment cmnt(masm_, "[ Literal"); |
| 595 Apply(expr->context(), expr); | 584 Apply(context_, expr); |
| 596 } | 585 } |
| 597 | 586 |
| 598 | 587 |
| 599 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 588 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
| 600 Comment cmnt(masm_, "[ Assignment"); | 589 Comment cmnt(masm_, "[ Assignment"); |
| 601 | |
| 602 // Left-hand side can only be a property, a global or a (parameter or local) | 590 // Left-hand side can only be a property, a global or a (parameter or local) |
| 603 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 591 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
| 604 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 592 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 605 LhsKind assign_type = VARIABLE; | 593 LhsKind assign_type = VARIABLE; |
| 606 Property* prop = expr->target()->AsProperty(); | 594 Property* prop = expr->target()->AsProperty(); |
| 607 // In case of a property we use the uninitialized expression context | |
| 608 // of the key to detect a named property. | |
| 609 if (prop != NULL) { | 595 if (prop != NULL) { |
| 610 assign_type = (prop->key()->context() == Expression::kUninitialized) | 596 assign_type = |
| 611 ? NAMED_PROPERTY | 597 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
| 612 : KEYED_PROPERTY; | |
| 613 } | 598 } |
| 614 | 599 |
| 615 // Evaluate LHS expression. | 600 // Evaluate LHS expression. |
| 616 switch (assign_type) { | 601 switch (assign_type) { |
| 617 case VARIABLE: | 602 case VARIABLE: |
| 618 // Nothing to do here. | 603 // Nothing to do here. |
| 619 break; | 604 break; |
| 620 case NAMED_PROPERTY: | 605 case NAMED_PROPERTY: |
| 621 VisitForValue(prop->obj(), kStack); | 606 VisitForValue(prop->obj(), kStack); |
| 622 break; | 607 break; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 location_ = saved_location; | 645 location_ = saved_location; |
| 661 } | 646 } |
| 662 | 647 |
| 663 // Record source position before possible IC call. | 648 // Record source position before possible IC call. |
| 664 SetSourcePosition(expr->position()); | 649 SetSourcePosition(expr->position()); |
| 665 | 650 |
| 666 // Store the value. | 651 // Store the value. |
| 667 switch (assign_type) { | 652 switch (assign_type) { |
| 668 case VARIABLE: | 653 case VARIABLE: |
| 669 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), | 654 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
| 670 expr->context()); | 655 context_); |
| 671 break; | 656 break; |
| 672 case NAMED_PROPERTY: | 657 case NAMED_PROPERTY: |
| 673 EmitNamedPropertyAssignment(expr); | 658 EmitNamedPropertyAssignment(expr); |
| 674 break; | 659 break; |
| 675 case KEYED_PROPERTY: | 660 case KEYED_PROPERTY: |
| 676 EmitKeyedPropertyAssignment(expr); | 661 EmitKeyedPropertyAssignment(expr); |
| 677 break; | 662 break; |
| 678 } | 663 } |
| 679 } | 664 } |
| 680 | 665 |
| 681 | 666 |
| 682 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 667 void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
| 683 // Call runtime routine to allocate the catch extension object and | 668 // Call runtime routine to allocate the catch extension object and |
| 684 // assign the exception value to the catch variable. | 669 // assign the exception value to the catch variable. |
| 685 Comment cmnt(masm_, "[ CatchExtensionObject"); | 670 Comment cmnt(masm_, "[ CatchExtensionObject"); |
| 686 | |
| 687 VisitForValue(expr->key(), kStack); | 671 VisitForValue(expr->key(), kStack); |
| 688 VisitForValue(expr->value(), kStack); | 672 VisitForValue(expr->value(), kStack); |
| 689 | |
| 690 // Create catch extension object. | 673 // Create catch extension object. |
| 691 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); | 674 __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); |
| 692 | 675 Apply(context_, result_register()); |
| 693 __ push(result_register()); | |
| 694 } | 676 } |
| 695 | 677 |
| 696 | 678 |
| 697 void FastCodeGenerator::VisitThrow(Throw* expr) { | 679 void FastCodeGenerator::VisitThrow(Throw* expr) { |
| 698 Comment cmnt(masm_, "[ Throw"); | 680 Comment cmnt(masm_, "[ Throw"); |
| 699 VisitForValue(expr->exception(), kStack); | 681 VisitForValue(expr->exception(), kStack); |
| 700 __ CallRuntime(Runtime::kThrow, 1); | 682 __ CallRuntime(Runtime::kThrow, 1); |
| 701 // Never returns here. | 683 // Never returns here. |
| 702 } | 684 } |
| 703 | 685 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 716 __ Drop(stack_depth); | 698 __ Drop(stack_depth); |
| 717 __ PopTryHandler(); | 699 __ PopTryHandler(); |
| 718 return 0; | 700 return 0; |
| 719 } | 701 } |
| 720 | 702 |
| 721 | 703 |
| 722 #undef __ | 704 #undef __ |
| 723 | 705 |
| 724 | 706 |
| 725 } } // namespace v8::internal | 707 } } // namespace v8::internal |
| OLD | NEW |