Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/x64/fast-codegen-x64.cc

Issue 339082: Initial implementation of top-level compilation of expressions in test... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/ia32/fast-codegen-ia32.cc ('K') | « src/ia32/fast-codegen-ia32.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 // (3 + 1 + 3). 109 // (3 + 1 + 3).
110 const int kPadding = Debug::kX64JSReturnSequenceLength - 7; 110 const int kPadding = Debug::kX64JSReturnSequenceLength - 7;
111 for (int i = 0; i < kPadding; ++i) { 111 for (int i = 0; i < kPadding; ++i) {
112 masm_->int3(); 112 masm_->int3();
113 } 113 }
114 #endif 114 #endif
115 } 115 }
116 } 116 }
117 117
118 118
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 __ addq(rsp, Immediate(kPointerSize));
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 __ addq(rsp, Immediate(kPointerSize));
147 __ jmp(true_label_);
148 break;
149 }
150 }
151 }
152
153
119 void FastCodeGenerator::Move(Expression::Context context, Slot* source) { 154 void FastCodeGenerator::Move(Expression::Context context, Slot* source) {
120 switch (context) { 155 switch (context) {
121 case Expression::kUninitialized: 156 case Expression::kUninitialized:
122 UNREACHABLE(); 157 UNREACHABLE();
123 case Expression::kEffect: 158 case Expression::kEffect:
124 break; 159 break;
125 case Expression::kValue: 160 case Expression::kValue:
126 __ push(Operand(rbp, SlotOffset(source))); 161 __ push(Operand(rbp, SlotOffset(source)));
127 break; 162 break;
163 case Expression::kTest: // Fall through.
164 case Expression::kValueTest: // Fall through.
165 case Expression::kTestValue:
166 __ movq(rax, Operand(rbp, SlotOffset(source)));
167 Move(context, rax);
168 break;
128 } 169 }
129 } 170 }
130 171
131 172
132 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { 173 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
133 switch (context) { 174 switch (context) {
134 case Expression::kUninitialized: 175 case Expression::kUninitialized:
135 UNREACHABLE(); 176 UNREACHABLE();
136 case Expression::kEffect: 177 case Expression::kEffect:
137 break; 178 break;
138 case Expression::kValue: 179 case Expression::kValue:
139 __ Push(expr->handle()); 180 __ Push(expr->handle());
140 break; 181 break;
182 case Expression::kTest: // Fall through.
183 case Expression::kValueTest: // Fall through.
184 case Expression::kTestValue:
185 __ Move(rax, expr->handle());
186 Move(context, rax);
187 break;
141 } 188 }
142 } 189 }
143 190
144 191
145 void FastCodeGenerator::DropAndMove(Expression::Context context, 192 void FastCodeGenerator::DropAndMove(Expression::Context context,
146 Register source) { 193 Register source) {
147 switch (context) { 194 switch (context) {
148 case Expression::kUninitialized: 195 case Expression::kUninitialized:
149 UNREACHABLE(); 196 UNREACHABLE();
150 case Expression::kEffect: 197 case Expression::kEffect:
151 __ addq(rsp, Immediate(kPointerSize)); 198 __ addq(rsp, Immediate(kPointerSize));
152 break; 199 break;
153 case Expression::kValue: 200 case Expression::kValue:
154 __ movq(Operand(rsp, 0), source); 201 __ movq(Operand(rsp, 0), source);
155 break; 202 break;
203 case Expression::kTest:
204 ASSERT(!source.is(rsp));
205 __ addq(rsp, Immediate(kPointerSize));
206 TestAndBranch(source, true_label_, false_label_);
207 break;
208 case Expression::kValueTest: {
209 Label discard;
210 __ movq(Operand(rsp, 0), source);
211 TestAndBranch(source, true_label_, &discard);
212 __ bind(&discard);
213 __ addq(rsp, Immediate(kPointerSize));
214 __ jmp(false_label_);
215 break;
216 }
217 case Expression::kTestValue: {
218 Label discard;
219 __ movq(Operand(rsp, 0), source);
220 TestAndBranch(source, &discard, false_label_);
221 __ bind(&discard);
222 __ addq(rsp, Immediate(kPointerSize));
223 __ jmp(true_label_);
224 break;
225 }
156 } 226 }
157 } 227 }
158 228
159 229
230 void FastCodeGenerator::TestAndBranch(Register source,
231 Label* true_label,
232 Label* false_label) {
233 ASSERT_NE(NULL, true_label);
234 ASSERT_NE(NULL, false_label);
235 // Use the shared ToBoolean stub to compile the value in the register into
236 // control flow to the code generator's true and false labels. Perform
237 // the fast checks assumed by the stub.
238
239 // The undefined value is false.
240 __ CompareRoot(source, Heap::kUndefinedValueRootIndex);
241 __ j(equal, false_label);
242 __ CompareRoot(source, Heap::kTrueValueRootIndex); // True is true.
243 __ j(equal, true_label);
244 __ CompareRoot(source, Heap::kFalseValueRootIndex); // False is false.
245 __ j(equal, false_label);
246 ASSERT_EQ(0, kSmiTag);
247 __ SmiCompare(source, Smi::FromInt(0)); // The smi zero is false.
248 __ j(equal, false_label);
249 Condition is_smi = masm_->CheckSmi(source); // All other smis are true.
250 __ j(is_smi, true_label);
251
252 // Call the stub for all other cases.
253 __ push(source);
254 ToBooleanStub stub;
255 __ CallStub(&stub);
256 __ testq(rax, rax); // The stub returns nonzero for true.
257 __ j(not_zero, true_label);
258 __ jmp(false_label);
259 }
260
261
160 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 262 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
161 // Call the runtime to declare the globals. 263 // Call the runtime to declare the globals.
162 __ push(rsi); // The context is the first argument. 264 __ push(rsi); // The context is the first argument.
163 __ Push(pairs); 265 __ Push(pairs);
164 __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); 266 __ Push(Smi::FromInt(is_eval_ ? 1 : 0));
165 __ CallRuntime(Runtime::kDeclareGlobals, 3); 267 __ CallRuntime(Runtime::kDeclareGlobals, 3);
166 // Return value is ignored. 268 // Return value is ignored.
167 } 269 }
168 270
169 271
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 } 456 }
355 switch (expr->context()) { 457 switch (expr->context()) {
356 case Expression::kUninitialized: 458 case Expression::kUninitialized:
357 UNREACHABLE(); 459 UNREACHABLE();
358 case Expression::kEffect: 460 case Expression::kEffect:
359 if (result_saved) __ addq(rsp, Immediate(kPointerSize)); 461 if (result_saved) __ addq(rsp, Immediate(kPointerSize));
360 break; 462 break;
361 case Expression::kValue: 463 case Expression::kValue:
362 if (!result_saved) __ push(rax); 464 if (!result_saved) __ push(rax);
363 break; 465 break;
466 case Expression::kTest:
467 if (result_saved) __ pop(rax);
468 TestAndBranch(rax, true_label_, false_label_);
469 break;
470 case Expression::kValueTest: {
471 Label discard;
472 if (!result_saved) __ push(rax);
473 TestAndBranch(rax, true_label_, &discard);
474 __ bind(&discard);
475 __ addq(rsp, Immediate(kPointerSize));
476 __ jmp(false_label_);
477 break;
478 }
479 case Expression::kTestValue: {
480 Label discard;
481 if (!result_saved) __ push(rax);
482 TestAndBranch(rax, &discard, false_label_);
483 __ bind(&discard);
484 __ addq(rsp, Immediate(kPointerSize));
485 __ jmp(true_label_);
486 break;
487 }
364 } 488 }
365 } 489 }
366 490
367 491
368 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 492 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
369 Comment cmnt(masm_, "[ ArrayLiteral"); 493 Comment cmnt(masm_, "[ ArrayLiteral");
370 Label make_clone; 494 Label make_clone;
371 495
372 // Fetch the function's literals array. 496 // Fetch the function's literals array.
373 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 497 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 552
429 switch (expr->context()) { 553 switch (expr->context()) {
430 case Expression::kUninitialized: 554 case Expression::kUninitialized:
431 UNREACHABLE(); 555 UNREACHABLE();
432 case Expression::kEffect: 556 case Expression::kEffect:
433 if (result_saved) __ addq(rsp, Immediate(kPointerSize)); 557 if (result_saved) __ addq(rsp, Immediate(kPointerSize));
434 break; 558 break;
435 case Expression::kValue: 559 case Expression::kValue:
436 if (!result_saved) __ push(rax); 560 if (!result_saved) __ push(rax);
437 break; 561 break;
562 case Expression::kTest:
563 if (result_saved) __ pop(rax);
564 TestAndBranch(rax, true_label_, false_label_);
565 break;
566 case Expression::kValueTest: {
567 Label discard;
568 if (!result_saved) __ push(rax);
569 TestAndBranch(rax, true_label_, &discard);
570 __ bind(&discard);
571 __ addq(rsp, Immediate(kPointerSize));
572 __ jmp(false_label_);
573 break;
574 }
575 case Expression::kTestValue: {
576 Label discard;
577 if (!result_saved) __ push(rax);
578 TestAndBranch(rax, &discard, false_label_);
579 __ bind(&discard);
580 __ addq(rsp, Immediate(kPointerSize));
581 __ jmp(true_label_);
582 break;
583 }
438 } 584 }
439 } 585 }
440 586
441 587
442 void FastCodeGenerator::VisitAssignment(Assignment* expr) { 588 void FastCodeGenerator::VisitAssignment(Assignment* expr) {
443 Comment cmnt(masm_, "[ Assignment"); 589 Comment cmnt(masm_, "[ Assignment");
444 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); 590 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
445 591
446 // Record the source position for the assignment. 592 // Record the source position for the assignment.
447 SetSourcePosition(expr->position()); 593 SetSourcePosition(expr->position());
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 case Expression::kEffect: 666 case Expression::kEffect:
521 // Case 'var = temp'. Discard right-hand-side temporary. 667 // Case 'var = temp'. Discard right-hand-side temporary.
522 __ pop(Operand(rbp, SlotOffset(var->slot()))); 668 __ pop(Operand(rbp, SlotOffset(var->slot())));
523 break; 669 break;
524 case Expression::kValue: 670 case Expression::kValue:
525 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side 671 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
526 // temporary on the stack. 672 // temporary on the stack.
527 __ movq(kScratchRegister, Operand(rsp, 0)); 673 __ movq(kScratchRegister, Operand(rsp, 0));
528 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); 674 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
529 break; 675 break;
676 case Expression::kTest:
677 // Case 'if (var = temp) ...'.
678 __ pop(rax);
679 __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
680 TestAndBranch(rax, true_label_, false_label_);
William Hesse 2009/10/30 12:09:39 Maybe we should have an operation "TestDropAndBran
Kevin Millikin (Chromium) 2009/10/30 13:45:53 Possibly. This whole chunk of platform-specific c
681 break;
682 case Expression::kValueTest: {
683 // Case '(var = temp) || ...' in value context.
684 Label discard;
685 __ movq(rax, Operand(rsp, 0));
686 __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
687 TestAndBranch(rax, true_label_, &discard);
688 __ bind(&discard);
689 __ addq(rsp, Immediate(kPointerSize));
690 __ jmp(false_label_);
691 break;
692 }
693 case Expression::kTestValue: {
694 // Case '(var = temp) && ...' in value context.
695 Label discard;
696 __ movq(rax, Operand(rsp, 0));
697 __ movq(Operand(rbp, SlotOffset(var->slot())), rax);
698 TestAndBranch(rax, &discard, false_label_);
699 __ bind(&discard);
700 __ addq(rsp, Immediate(kPointerSize));
701 __ jmp(true_label_);
702 break;
703 }
530 } 704 }
531 } 705 }
532 } 706 }
533 } 707 }
534 708
535 709
536 void FastCodeGenerator::VisitProperty(Property* expr) { 710 void FastCodeGenerator::VisitProperty(Property* expr) {
537 Comment cmnt(masm_, "[ Property"); 711 Comment cmnt(masm_, "[ Property");
538 Expression* key = expr->key(); 712 Expression* key = expr->key();
539 uint32_t dummy; 713 uint32_t dummy;
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 Move(expr->context(), rax); 867 Move(expr->context(), rax);
694 868
695 break; 869 break;
696 } 870 }
697 default: 871 default:
698 UNREACHABLE(); 872 UNREACHABLE();
699 } 873 }
700 } 874 }
701 875
702 876
703 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
704 // Compile a short-circuited boolean operation in a non-test context.
705
706 // Compile (e0 || e1) as if it were
707 // (let (temp = e0) temp ? temp : e1).
708 // Compile (e0 && e1) as if it were
709 // (let (temp = e0) !temp ? temp : e1).
710
711 Label eval_right, done;
712 Label *left_true, *left_false; // Where to branch to if lhs has that value.
713 if (expr->op() == Token::OR) {
714 left_true = &done;
715 left_false = &eval_right;
716 } else {
717 left_true = &eval_right;
718 left_false = &done;
719 }
720 Expression::Context context = expr->context();
721 Expression* left = expr->left();
722 Expression* right = expr->right();
723
724 // Use the shared ToBoolean stub to find the boolean value of the
725 // left-hand subexpression. Load the value into rax to perform some
726 // inlined checks assumed by the stub.
727
728 // Compile the left-hand value into rax. Put it on the stack if we may
729 // need it as the value of the whole expression.
730 if (left->AsLiteral() != NULL) {
731 __ Move(rax, left->AsLiteral()->handle());
732 if (context == Expression::kValue) __ push(rax);
733 } else {
734 Visit(left);
735 ASSERT_EQ(Expression::kValue, left->context());
736 switch (context) {
737 case Expression::kUninitialized:
738 UNREACHABLE();
739 case Expression::kEffect:
740 // Pop the left-hand value into rax because we will not need it as the
741 // final result.
742 __ pop(rax);
743 break;
744 case Expression::kValue:
745 // Copy the left-hand value into rax because we may need it as the
746 // final result.
747 __ movq(rax, Operand(rsp, 0));
748 break;
749 }
750 }
751 // The left-hand value is in rax. It is also on the stack iff the
752 // destination location is value.
753
754 // Perform fast checks assumed by the stub.
755 // The undefined value is false.
756 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
757 __ j(equal, left_false);
758 __ CompareRoot(rax, Heap::kTrueValueRootIndex); // True is true.
759 __ j(equal, left_true);
760 __ CompareRoot(rax, Heap::kFalseValueRootIndex); // False is false.
761 __ j(equal, left_false);
762 ASSERT(kSmiTag == 0);
763 __ SmiCompare(rax, Smi::FromInt(0)); // The smi zero is false.
764 __ j(equal, left_false);
765 Condition is_smi = masm_->CheckSmi(rax); // All other smis are true.
766 __ j(is_smi, left_true);
767
768 // Call the stub for all other cases.
769 __ push(rax);
770 ToBooleanStub stub;
771 __ CallStub(&stub);
772 __ testq(rax, rax); // The stub returns nonzero for true.
773 if (expr->op() == Token::OR) {
774 __ j(not_zero, &done);
775 } else {
776 __ j(zero, &done);
777 }
778
779 __ bind(&eval_right);
780 // Discard the left-hand value if present on the stack.
781 if (context == Expression::kValue) {
782 __ addq(rsp, Immediate(kPointerSize));
783 }
784 // Save or discard the right-hand value as needed.
785 Visit(right);
786 ASSERT_EQ(context, right->context());
787
788 __ bind(&done);
789 }
790
791
792 } } // namespace v8::internal 877 } } // namespace v8::internal
OLDNEW
« src/ia32/fast-codegen-ia32.cc ('K') | « src/ia32/fast-codegen-ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698