| 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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 __ RecordJSReturn(); | 110 __ RecordJSReturn(); |
| 111 __ mov(sp, fp); | 111 __ mov(sp, fp); |
| 112 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 112 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 113 int num_parameters = function_->scope()->num_parameters(); | 113 int num_parameters = function_->scope()->num_parameters(); |
| 114 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); | 114 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); |
| 115 __ Jump(lr); | 115 __ Jump(lr); |
| 116 } | 116 } |
| 117 } | 117 } |
| 118 | 118 |
| 119 | 119 |
| 120 void FastCodeGenerator::Move(Expression::Context context, Register source) { |
| 121 switch (context) { |
| 122 case Expression::kUninitialized: |
| 123 UNREACHABLE(); |
| 124 case Expression::kEffect: |
| 125 break; |
| 126 case Expression::kValue: |
| 127 __ push(source); |
| 128 break; |
| 129 case Expression::kTest: |
| 130 TestAndBranch(source, true_label_, false_label_); |
| 131 break; |
| 132 case Expression::kValueTest: { |
| 133 Label discard; |
| 134 __ push(source); |
| 135 TestAndBranch(source, true_label_, &discard); |
| 136 __ bind(&discard); |
| 137 __ pop(); |
| 138 __ jmp(false_label_); |
| 139 break; |
| 140 } |
| 141 case Expression::kTestValue: { |
| 142 Label discard; |
| 143 __ push(source); |
| 144 TestAndBranch(source, &discard, false_label_); |
| 145 __ bind(&discard); |
| 146 __ pop(); |
| 147 __ jmp(true_label_); |
| 148 } |
| 149 } |
| 150 } |
| 151 |
| 152 |
| 120 void FastCodeGenerator::Move(Expression::Context context, Slot* source) { | 153 void FastCodeGenerator::Move(Expression::Context context, Slot* source) { |
| 121 switch (context) { | 154 switch (context) { |
| 122 case Expression::kUninitialized: | 155 case Expression::kUninitialized: |
| 123 UNREACHABLE(); | 156 UNREACHABLE(); |
| 124 case Expression::kEffect: | 157 case Expression::kEffect: |
| 125 break; | 158 break; |
| 126 case Expression::kValue: | 159 case Expression::kValue: // Fall through. |
| 160 case Expression::kTest: // Fall through. |
| 161 case Expression::kValueTest: // Fall through. |
| 162 case Expression::kTestValue: |
| 127 __ ldr(ip, MemOperand(fp, SlotOffset(source))); | 163 __ ldr(ip, MemOperand(fp, SlotOffset(source))); |
| 128 __ push(ip); | 164 Move(context, ip); |
| 129 break; | 165 break; |
| 130 } | 166 } |
| 131 } | 167 } |
| 132 | 168 |
| 133 | 169 |
| 134 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { | 170 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { |
| 135 switch (context) { | 171 switch (context) { |
| 136 case Expression::kUninitialized: | 172 case Expression::kUninitialized: |
| 137 UNREACHABLE(); | 173 UNREACHABLE(); |
| 138 case Expression::kEffect: | 174 case Expression::kEffect: |
| 139 break; | 175 break; |
| 140 case Expression::kValue: | 176 case Expression::kValue: // Fall through. |
| 177 case Expression::kTest: // Fall through. |
| 178 case Expression::kValueTest: // Fall through. |
| 179 case Expression::kTestValue: |
| 141 __ mov(ip, Operand(expr->handle())); | 180 __ mov(ip, Operand(expr->handle())); |
| 142 __ push(ip); | 181 Move(context, ip); |
| 143 break; | 182 break; |
| 144 } | 183 } |
| 145 } | 184 } |
| 146 | 185 |
| 147 | 186 |
| 148 void FastCodeGenerator::DropAndMove(Expression::Context context, | 187 void FastCodeGenerator::DropAndMove(Expression::Context context, |
| 149 Register source) { | 188 Register source) { |
| 150 switch (context) { | 189 switch (context) { |
| 151 case Expression::kUninitialized: | 190 case Expression::kUninitialized: |
| 152 UNREACHABLE(); | 191 UNREACHABLE(); |
| 153 case Expression::kEffect: | 192 case Expression::kEffect: |
| 154 __ pop(); | 193 __ pop(); |
| 155 break; | 194 break; |
| 156 case Expression::kValue: | 195 case Expression::kValue: |
| 157 __ str(source, MemOperand(sp)); | 196 __ str(source, MemOperand(sp)); |
| 158 break; | 197 break; |
| 198 case Expression::kTest: |
| 199 ASSERT(!source.is(sp)); |
| 200 __ pop(); |
| 201 TestAndBranch(source, true_label_, false_label_); |
| 202 break; |
| 203 case Expression::kValueTest: { |
| 204 Label discard; |
| 205 __ str(source, MemOperand(sp)); |
| 206 TestAndBranch(source, true_label_, &discard); |
| 207 __ bind(&discard); |
| 208 __ pop(); |
| 209 __ jmp(false_label_); |
| 210 break; |
| 211 } |
| 212 case Expression::kTestValue: { |
| 213 Label discard; |
| 214 __ str(source, MemOperand(sp)); |
| 215 TestAndBranch(source, &discard, false_label_); |
| 216 __ bind(&discard); |
| 217 __ pop(); |
| 218 __ jmp(true_label_); |
| 219 break; |
| 220 } |
| 159 } | 221 } |
| 160 } | 222 } |
| 161 | 223 |
| 162 | 224 |
| 225 void FastCodeGenerator::TestAndBranch(Register source, |
| 226 Label* true_label, |
| 227 Label* false_label) { |
| 228 ASSERT_NE(NULL, true_label); |
| 229 ASSERT_NE(NULL, false_label); |
| 230 // Call the runtime to find the boolean value of the source and then |
| 231 // translate it into control flow to the pair of labels. |
| 232 __ push(source); |
| 233 __ CallRuntime(Runtime::kToBool, 1); |
| 234 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 235 __ cmp(r0, ip); |
| 236 __ b(eq, true_label); |
| 237 __ jmp(false_label); |
| 238 } |
| 239 |
| 240 |
| 163 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 241 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 164 // Call the runtime to declare the globals. | 242 // Call the runtime to declare the globals. |
| 165 // The context is the first argument. | 243 // The context is the first argument. |
| 166 __ mov(r1, Operand(pairs)); | 244 __ mov(r1, Operand(pairs)); |
| 167 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); | 245 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); |
| 168 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); | 246 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); |
| 169 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 247 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
| 170 // Return value is ignored. | 248 // Return value is ignored. |
| 171 } | 249 } |
| 172 | 250 |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 } | 431 } |
| 354 switch (expr->context()) { | 432 switch (expr->context()) { |
| 355 case Expression::kUninitialized: | 433 case Expression::kUninitialized: |
| 356 UNREACHABLE(); | 434 UNREACHABLE(); |
| 357 case Expression::kEffect: | 435 case Expression::kEffect: |
| 358 if (result_saved) __ pop(); | 436 if (result_saved) __ pop(); |
| 359 break; | 437 break; |
| 360 case Expression::kValue: | 438 case Expression::kValue: |
| 361 if (!result_saved) __ push(r0); | 439 if (!result_saved) __ push(r0); |
| 362 break; | 440 break; |
| 441 case Expression::kTest: |
| 442 if (result_saved) __ pop(r0); |
| 443 TestAndBranch(r0, true_label_, false_label_); |
| 444 break; |
| 445 case Expression::kValueTest: { |
| 446 Label discard; |
| 447 if (!result_saved) __ push(r0); |
| 448 TestAndBranch(r0, true_label_, &discard); |
| 449 __ bind(&discard); |
| 450 __ pop(); |
| 451 __ jmp(false_label_); |
| 452 break; |
| 453 } |
| 454 case Expression::kTestValue: { |
| 455 Label discard; |
| 456 if (!result_saved) __ push(r0); |
| 457 TestAndBranch(r0, &discard, false_label_); |
| 458 __ bind(&discard); |
| 459 __ pop(); |
| 460 __ jmp(true_label_); |
| 461 break; |
| 462 } |
| 363 } | 463 } |
| 364 } | 464 } |
| 365 | 465 |
| 366 | 466 |
| 367 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 467 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 368 Comment cmnt(masm_, "[ ArrayLiteral"); | 468 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 369 Label make_clone; | 469 Label make_clone; |
| 370 | 470 |
| 371 // Fetch the function's literals array. | 471 // Fetch the function's literals array. |
| 372 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 472 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 | 530 |
| 431 switch (expr->context()) { | 531 switch (expr->context()) { |
| 432 case Expression::kUninitialized: | 532 case Expression::kUninitialized: |
| 433 UNREACHABLE(); | 533 UNREACHABLE(); |
| 434 case Expression::kEffect: | 534 case Expression::kEffect: |
| 435 if (result_saved) __ pop(); | 535 if (result_saved) __ pop(); |
| 436 break; | 536 break; |
| 437 case Expression::kValue: | 537 case Expression::kValue: |
| 438 if (!result_saved) __ push(r0); | 538 if (!result_saved) __ push(r0); |
| 439 break; | 539 break; |
| 540 case Expression::kTest: |
| 541 if (result_saved) __ pop(r0); |
| 542 TestAndBranch(r0, true_label_, false_label_); |
| 543 break; |
| 544 case Expression::kValueTest: { |
| 545 Label discard; |
| 546 if (!result_saved) __ push(r0); |
| 547 TestAndBranch(r0, true_label_, &discard); |
| 548 __ bind(&discard); |
| 549 __ pop(); |
| 550 __ jmp(false_label_); |
| 551 break; |
| 552 } |
| 553 case Expression::kTestValue: { |
| 554 Label discard; |
| 555 if (!result_saved) __ push(r0); |
| 556 TestAndBranch(r0, &discard, false_label_); |
| 557 __ bind(&discard); |
| 558 __ pop(); |
| 559 __ jmp(true_label_); |
| 560 break; |
| 561 } |
| 440 } | 562 } |
| 441 } | 563 } |
| 442 | 564 |
| 443 | 565 |
| 444 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 566 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
| 445 Comment cmnt(masm_, "[ Assignment"); | 567 Comment cmnt(masm_, "[ Assignment"); |
| 446 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 568 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); |
| 447 | 569 |
| 448 // Record the source position for the assignment. | 570 // Record the source position for the assignment. |
| 449 SetSourcePosition(expr->position()); | 571 SetSourcePosition(expr->position()); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 Move(expr->context(), ip); | 636 Move(expr->context(), ip); |
| 515 } else { | 637 } else { |
| 516 ASSERT_EQ(Expression::kValue, rhs->context()); | 638 ASSERT_EQ(Expression::kValue, rhs->context()); |
| 517 Visit(rhs); | 639 Visit(rhs); |
| 518 // Load right-hand side into ip. | 640 // Load right-hand side into ip. |
| 519 switch (expr->context()) { | 641 switch (expr->context()) { |
| 520 case Expression::kUninitialized: | 642 case Expression::kUninitialized: |
| 521 UNREACHABLE(); | 643 UNREACHABLE(); |
| 522 case Expression::kEffect: | 644 case Expression::kEffect: |
| 523 // Case 'var = temp'. Discard right-hand-side temporary. | 645 // Case 'var = temp'. Discard right-hand-side temporary. |
| 524 __ pop(ip); | 646 __ pop(r0); |
| 647 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 525 break; | 648 break; |
| 526 case Expression::kValue: | 649 case Expression::kValue: |
| 527 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side | 650 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side |
| 528 // temporary on the stack. | 651 // temporary on the stack. |
| 529 __ ldr(ip, MemOperand(sp)); | 652 __ ldr(r0, MemOperand(sp)); |
| 653 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 530 break; | 654 break; |
| 655 case Expression::kTest: |
| 656 // Case 'if (var = temp) ...'. |
| 657 __ pop(r0); |
| 658 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 659 TestAndBranch(r0, true_label_, false_label_); |
| 660 break; |
| 661 case Expression::kValueTest: { |
| 662 // Case '(var = temp) || ...' in value context. |
| 663 Label discard; |
| 664 __ ldr(r0, MemOperand(sp)); |
| 665 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 666 TestAndBranch(r0, true_label_, &discard); |
| 667 __ bind(&discard); |
| 668 __ pop(); |
| 669 __ jmp(false_label_); |
| 670 break; |
| 671 } |
| 672 case Expression::kTestValue: { |
| 673 // Case '(var = temp) && ...' in value context. |
| 674 Label discard; |
| 675 __ ldr(r0, MemOperand(sp)); |
| 676 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
| 677 TestAndBranch(r0, &discard, false_label_); |
| 678 __ bind(&discard); |
| 679 __ pop(); |
| 680 __ jmp(true_label_); |
| 681 break; |
| 682 } |
| 531 } | 683 } |
| 532 // Do the slot assignment. | |
| 533 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); | |
| 534 } | 684 } |
| 535 } | 685 } |
| 536 } | 686 } |
| 537 | 687 |
| 538 | 688 |
| 539 void FastCodeGenerator::VisitProperty(Property* expr) { | 689 void FastCodeGenerator::VisitProperty(Property* expr) { |
| 540 Comment cmnt(masm_, "[ Property"); | 690 Comment cmnt(masm_, "[ Property"); |
| 541 Expression* key = expr->key(); | 691 Expression* key = expr->key(); |
| 542 uint32_t dummy; | 692 uint32_t dummy; |
| 543 | 693 |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 Move(expr->context(), r0); | 841 Move(expr->context(), r0); |
| 692 | 842 |
| 693 break; | 843 break; |
| 694 } | 844 } |
| 695 default: | 845 default: |
| 696 UNREACHABLE(); | 846 UNREACHABLE(); |
| 697 } | 847 } |
| 698 } | 848 } |
| 699 | 849 |
| 700 | 850 |
| 701 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { | |
| 702 // Compile a short-circuited boolean operation in a non-test context. | |
| 703 | |
| 704 // Compile (e0 || e1) as if it were | |
| 705 // (let (temp = e0) temp ? temp : e1). | |
| 706 // Compile (e0 && e1) as if it were | |
| 707 // (let (temp = e0) !temp ? temp : e1). | |
| 708 | |
| 709 Label done; | |
| 710 Expression::Context context = expr->context(); | |
| 711 Expression* left = expr->left(); | |
| 712 Expression* right = expr->right(); | |
| 713 | |
| 714 // Call the runtime to find the boolean value of the left-hand | |
| 715 // subexpression. Duplicate the value if it may be needed as the final | |
| 716 // result. | |
| 717 if (left->AsLiteral() != NULL) { | |
| 718 __ mov(r0, Operand(left->AsLiteral()->handle())); | |
| 719 __ push(r0); | |
| 720 if (context == Expression::kValue) __ push(r0); | |
| 721 } else { | |
| 722 Visit(left); | |
| 723 ASSERT_EQ(Expression::kValue, left->context()); | |
| 724 if (context == Expression::kValue) { | |
| 725 __ ldr(r0, MemOperand(sp)); | |
| 726 __ push(r0); | |
| 727 } | |
| 728 } | |
| 729 // The left-hand value is in on top of the stack. It is duplicated on the | |
| 730 // stack iff the destination location is value. | |
| 731 __ CallRuntime(Runtime::kToBool, 1); | |
| 732 if (expr->op() == Token::OR) { | |
| 733 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | |
| 734 } else { | |
| 735 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | |
| 736 } | |
| 737 __ cmp(r0, ip); | |
| 738 __ b(eq, &done); | |
| 739 | |
| 740 // Discard the left-hand value if present on the stack. | |
| 741 if (context == Expression::kValue) __ pop(); | |
| 742 // Save or discard the right-hand value as needed. | |
| 743 Visit(right); | |
| 744 ASSERT_EQ(context, right->context()); | |
| 745 | |
| 746 __ bind(&done); | |
| 747 } | |
| 748 | |
| 749 } } // namespace v8::internal | 851 } } // namespace v8::internal |
| OLD | NEW |