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 |