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 |