| 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 |