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

Side by Side Diff: src/ia32/fast-codegen-ia32.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
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 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 __ RecordJSReturn(); 101 __ RecordJSReturn();
102 // Do not use the leave instruction here because it is too short to 102 // Do not use the leave instruction here because it is too short to
103 // patch with the code required by the debugger. 103 // patch with the code required by the debugger.
104 __ mov(esp, ebp); 104 __ mov(esp, ebp);
105 __ pop(ebp); 105 __ pop(ebp);
106 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize); 106 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize);
107 } 107 }
108 } 108 }
109 109
110 110
111 void FastCodeGenerator::Move(Expression::Context context, Register source) {
112 switch (context) {
113 case Expression::kUninitialized:
114 UNREACHABLE();
115 case Expression::kEffect:
116 break;
117 case Expression::kValue:
118 __ push(source);
119 break;
120 case Expression::kTest:
121 TestAndBranch(source, true_label_, false_label_);
122 break;
123 case Expression::kValueTest: {
124 Label discard;
125 __ push(source);
126 TestAndBranch(source, true_label_, &discard);
William Hesse 2009/10/30 12:09:39 Why not Label save; TestAndBranch(source, &save, f
Kevin Millikin (Chromium) 2009/10/30 13:45:53 TestAndBranch destroys source.
127 __ bind(&discard);
128 __ add(Operand(esp), Immediate(kPointerSize));
129 __ jmp(false_label_);
130 break;
131 }
132 case Expression::kTestValue: {
133 Label discard;
134 __ push(source);
135 TestAndBranch(source, &discard, false_label_);
136 __ bind(&discard);
137 __ add(Operand(esp), Immediate(kPointerSize));
138 __ jmp(true_label_);
139 }
140 }
141 }
142
143
111 void FastCodeGenerator::Move(Expression::Context context, Slot* source) { 144 void FastCodeGenerator::Move(Expression::Context context, Slot* source) {
112 switch (context) { 145 switch (context) {
113 case Expression::kUninitialized: 146 case Expression::kUninitialized:
114 UNREACHABLE(); 147 UNREACHABLE();
115 case Expression::kEffect: 148 case Expression::kEffect:
116 break; 149 break;
117 case Expression::kValue: 150 case Expression::kValue:
118 __ push(Operand(ebp, SlotOffset(source))); 151 __ push(Operand(ebp, SlotOffset(source)));
119 break; 152 break;
153 case Expression::kTest: // Fall through.
154 case Expression::kValueTest: // Fall through.
155 case Expression::kTestValue:
156 __ mov(eax, Operand(ebp, SlotOffset(source)));
William Hesse 2009/10/30 12:09:39 This could be optimized if TestAndBranch took an o
Kevin Millikin (Chromium) 2009/10/30 13:45:53 TestAndBranch needs the value in a register to com
157 Move(context, eax);
158 break;
120 } 159 }
121 } 160 }
122 161
123 162
124 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { 163 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
125 switch (context) { 164 switch (context) {
126 case Expression::kUninitialized: 165 case Expression::kUninitialized:
127 UNREACHABLE(); 166 UNREACHABLE();
128 case Expression::kEffect: 167 case Expression::kEffect:
129 break; 168 break;
130 case Expression::kValue: 169 case Expression::kValue:
131 __ push(Immediate(expr->handle())); 170 __ push(Immediate(expr->handle()));
132 break; 171 break;
172 case Expression::kTest: // Fall through.
173 case Expression::kValueTest: // Fall through.
174 case Expression::kTestValue:
175 __ mov(eax, expr->handle());
176 Move(context, eax);
177 break;
133 } 178 }
134 } 179 }
135 180
136 181
137 void FastCodeGenerator::DropAndMove(Expression::Context context, 182 void FastCodeGenerator::DropAndMove(Expression::Context context,
138 Register source) { 183 Register source) {
139 switch (context) { 184 switch (context) {
140 case Expression::kUninitialized: 185 case Expression::kUninitialized:
141 UNREACHABLE(); 186 UNREACHABLE();
142 case Expression::kEffect: 187 case Expression::kEffect:
143 __ add(Operand(esp), Immediate(kPointerSize)); 188 __ add(Operand(esp), Immediate(kPointerSize));
144 break; 189 break;
145 case Expression::kValue: 190 case Expression::kValue:
146 __ mov(Operand(esp, 0), source); 191 __ mov(Operand(esp, 0), source);
147 break; 192 break;
193 case Expression::kTest:
194 ASSERT(!source.is(esp));
195 __ add(Operand(esp), Immediate(kPointerSize));
196 TestAndBranch(source, true_label_, false_label_);
197 break;
198 case Expression::kValueTest: {
199 Label discard;
200 __ mov(Operand(esp, 0), source);
201 TestAndBranch(source, true_label_, &discard);
202 __ bind(&discard);
203 __ add(Operand(esp), Immediate(kPointerSize));
204 __ jmp(false_label_);
205 break;
206 }
207 case Expression::kTestValue: {
208 Label discard;
209 __ mov(Operand(esp, 0), source);
210 TestAndBranch(source, &discard, false_label_);
211 __ bind(&discard);
212 __ add(Operand(esp), Immediate(kPointerSize));
213 __ jmp(true_label_);
214 break;
215 }
148 } 216 }
149 } 217 }
150 218
151 219
220 void FastCodeGenerator::TestAndBranch(Register source,
221 Label* true_label,
222 Label* false_label) {
223 ASSERT_NE(NULL, true_label);
224 ASSERT_NE(NULL, false_label);
225 // Use the shared ToBoolean stub to compile the value in the register into
226 // control flow to the code generator's true and false labels. Perform
227 // the fast checks assumed by the stub.
228 __ cmp(source, Factory::undefined_value()); // The undefined value is false.
229 __ j(equal, false_label);
230 __ cmp(source, Factory::true_value()); // True is true.
231 __ j(equal, true_label);
232 __ cmp(source, Factory::false_value()); // False is false.
233 __ j(equal, false_label);
234 ASSERT_EQ(0, kSmiTag);
235 __ test(source, Operand(source)); // The smi zero is false.
236 __ j(zero, false_label);
237 __ test(source, Immediate(kSmiTagMask)); // All other smis are true.
238 __ j(zero, true_label);
239
240 // Call the stub for all other cases.
241 __ push(source);
242 ToBooleanStub stub;
243 __ CallStub(&stub);
244 __ test(eax, Operand(eax)); // The stub returns nonzero for true.
245 __ j(not_zero, true_label);
246 __ jmp(false_label);
247 }
248
249
152 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 250 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
153 // Call the runtime to declare the globals. 251 // Call the runtime to declare the globals.
154 __ push(esi); // The context is the first argument. 252 __ push(esi); // The context is the first argument.
155 __ push(Immediate(pairs)); 253 __ push(Immediate(pairs));
156 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); 254 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0)));
157 __ CallRuntime(Runtime::kDeclareGlobals, 3); 255 __ CallRuntime(Runtime::kDeclareGlobals, 3);
158 // Return value is ignored. 256 // Return value is ignored.
159 } 257 }
160 258
161 259
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 } 441 }
344 switch (expr->context()) { 442 switch (expr->context()) {
345 case Expression::kUninitialized: 443 case Expression::kUninitialized:
346 UNREACHABLE(); 444 UNREACHABLE();
347 case Expression::kEffect: 445 case Expression::kEffect:
348 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); 446 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
349 break; 447 break;
350 case Expression::kValue: 448 case Expression::kValue:
351 if (!result_saved) __ push(eax); 449 if (!result_saved) __ push(eax);
352 break; 450 break;
451 case Expression::kTest:
452 if (result_saved) __ pop(eax);
453 TestAndBranch(eax, true_label_, false_label_);
454 break;
455 case Expression::kValueTest: {
456 Label discard;
457 if (!result_saved) __ push(eax);
458 TestAndBranch(eax, true_label_, &discard);
459 __ bind(&discard);
460 __ add(Operand(esp), Immediate(kPointerSize));
461 __ jmp(false_label_);
462 break;
463 }
464 case Expression::kTestValue: {
465 Label discard;
466 if (!result_saved) __ push(eax);
467 TestAndBranch(eax, &discard, false_label_);
468 __ bind(&discard);
469 __ add(Operand(esp), Immediate(kPointerSize));
470 __ jmp(true_label_);
471 break;
472 }
353 } 473 }
354 } 474 }
355 475
356 476
357 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 477 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
358 Comment cmnt(masm_, "[ ArrayLiteral"); 478 Comment cmnt(masm_, "[ ArrayLiteral");
359 Label make_clone; 479 Label make_clone;
360 480
361 // Fetch the function's literals array. 481 // Fetch the function's literals array.
362 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 482 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 537
418 switch (expr->context()) { 538 switch (expr->context()) {
419 case Expression::kUninitialized: 539 case Expression::kUninitialized:
420 UNREACHABLE(); 540 UNREACHABLE();
421 case Expression::kEffect: 541 case Expression::kEffect:
422 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); 542 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
423 break; 543 break;
424 case Expression::kValue: 544 case Expression::kValue:
425 if (!result_saved) __ push(eax); 545 if (!result_saved) __ push(eax);
426 break; 546 break;
547 case Expression::kTest:
548 if (result_saved) __ pop(eax);
549 TestAndBranch(eax, true_label_, false_label_);
550 break;
551 case Expression::kValueTest: {
552 Label discard;
553 if (!result_saved) __ push(eax);
554 TestAndBranch(eax, true_label_, &discard);
555 __ bind(&discard);
556 __ add(Operand(esp), Immediate(kPointerSize));
557 __ jmp(false_label_);
558 break;
559 }
560 case Expression::kTestValue: {
561 Label discard;
562 if (!result_saved) __ push(eax);
563 TestAndBranch(eax, &discard, false_label_);
564 __ bind(&discard);
565 __ add(Operand(esp), Immediate(kPointerSize));
566 __ jmp(true_label_);
567 break;
568 }
427 } 569 }
428 } 570 }
429 571
430 572
431 void FastCodeGenerator::VisitAssignment(Assignment* expr) { 573 void FastCodeGenerator::VisitAssignment(Assignment* expr) {
432 Comment cmnt(masm_, "[ Assignment"); 574 Comment cmnt(masm_, "[ Assignment");
433 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); 575 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
434 576
435 // Record the source position for the assignment. 577 // Record the source position for the assignment.
436 SetSourcePosition(expr->position()); 578 SetSourcePosition(expr->position());
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 case Expression::kEffect: 652 case Expression::kEffect:
511 // Case 'var = temp'. Discard right-hand-side temporary. 653 // Case 'var = temp'. Discard right-hand-side temporary.
512 __ pop(Operand(ebp, SlotOffset(var->slot()))); 654 __ pop(Operand(ebp, SlotOffset(var->slot())));
513 break; 655 break;
514 case Expression::kValue: 656 case Expression::kValue:
515 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side 657 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
516 // temporary on the stack. 658 // temporary on the stack.
517 __ mov(eax, Operand(esp, 0)); 659 __ mov(eax, Operand(esp, 0));
518 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); 660 __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
519 break; 661 break;
662 case Expression::kTest:
663 // Case 'if (var = temp) ...'.
664 __ pop(eax);
665 __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
666 TestAndBranch(eax, true_label_, false_label_);
667 break;
668 case Expression::kValueTest: {
669 // Case '(var = temp) || ...' in value context.
670 Label discard;
William Hesse 2009/10/30 12:09:39 Same comment as above, on optimization.
671 __ mov(eax, Operand(esp, 0));
672 __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
673 TestAndBranch(eax, true_label_, &discard);
William Hesse 2009/10/30 12:09:39 Can we give TestAndBranch a fallthrough label, so
Kevin Millikin (Chromium) 2009/10/30 13:45:53 We'd need a global fallthrough to get the whole be
674 __ bind(&discard);
675 __ add(Operand(esp), Immediate(kPointerSize));
676 __ jmp(false_label_);
677 break;
678 }
679 case Expression::kTestValue: {
680 // Case '(var = temp) && ...' in value context.
681 Label discard;
682 __ mov(eax, Operand(esp, 0));
683 __ mov(Operand(ebp, SlotOffset(var->slot())), eax);
684 TestAndBranch(eax, &discard, false_label_);
685 __ bind(&discard);
686 __ add(Operand(esp), Immediate(kPointerSize));
687 __ jmp(true_label_);
688 break;
689 }
520 } 690 }
521 } 691 }
522 } 692 }
523 } 693 }
524 694
525 695
526 void FastCodeGenerator::VisitProperty(Property* expr) { 696 void FastCodeGenerator::VisitProperty(Property* expr) {
527 Comment cmnt(masm_, "[ Property"); 697 Comment cmnt(masm_, "[ Property");
528 Expression* key = expr->key(); 698 Expression* key = expr->key();
529 uint32_t dummy; 699 uint32_t dummy;
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 Move(expr->context(), eax); 851 Move(expr->context(), eax);
682 852
683 break; 853 break;
684 } 854 }
685 default: 855 default:
686 UNREACHABLE(); 856 UNREACHABLE();
687 } 857 }
688 } 858 }
689 859
690 860
691 void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { 861 #undef __
692 // Compile a short-circuited boolean operation in a non-test context.
693
694 // Compile (e0 || e1) or (e0 && e1) as if it were
695 // (let (temp = e0) temp [or !temp, for &&] ? temp : e1).
696
697 Label eval_right, done;
698 Label *left_true, *left_false; // Where to branch to if lhs has that value.
699 if (expr->op() == Token::OR) {
700 left_true = &done;
701 left_false = &eval_right;
702 } else {
703 left_true = &eval_right;
704 left_false = &done;
705 }
706 Expression::Context context = expr->context();
707 Expression* left = expr->left();
708 Expression* right = expr->right();
709
710 // Use the shared ToBoolean stub to find the boolean value of the
711 // left-hand subexpression. Load the value into eax to perform some
712 // inlined checks assumed by the stub.
713
714 // Compile the left-hand value into eax. Put it on the stack if we may
715 // need it as the value of the whole expression.
716 if (left->AsLiteral() != NULL) {
717 __ mov(eax, left->AsLiteral()->handle());
718 if (context == Expression::kValue) __ push(eax);
719 } else {
720 Visit(left);
721 ASSERT_EQ(Expression::kValue, left->context());
722 switch (context) {
723 case Expression::kUninitialized:
724 UNREACHABLE();
725 case Expression::kEffect:
726 // Pop the left-hand value into eax because we will not need it as the
727 // final result.
728 __ pop(eax);
729 break;
730 case Expression::kValue:
731 // Copy the left-hand value into eax because we may need it as the
732 // final result.
733 __ mov(eax, Operand(esp, 0));
734 break;
735 }
736 }
737 // The left-hand value is in eax. It is also on the stack iff the
738 // destination location is value.
739
740 // Perform fast checks assumed by the stub.
741 __ cmp(eax, Factory::undefined_value()); // The undefined value is false.
742 __ j(equal, left_false);
743 __ cmp(eax, Factory::true_value()); // True is true.
744 __ j(equal, left_true);
745 __ cmp(eax, Factory::false_value()); // False is false.
746 __ j(equal, left_false);
747 ASSERT_EQ(0, kSmiTag);
748 __ test(eax, Operand(eax)); // The smi zero is false.
749 __ j(zero, left_false);
750 __ test(eax, Immediate(kSmiTagMask)); // All other smis are true.
751 __ j(zero, left_true);
752
753 // Call the stub for all other cases.
754 __ push(eax);
755 ToBooleanStub stub;
756 __ CallStub(&stub);
757 __ test(eax, Operand(eax)); // The stub returns nonzero for true.
758 if (expr->op() == Token::OR) {
759 __ j(not_zero, &done);
760 } else {
761 __ j(zero, &done);
762 }
763
764 __ bind(&eval_right);
765 // Discard the left-hand value if present on the stack.
766 if (context == Expression::kValue) {
767 __ add(Operand(esp), Immediate(kPointerSize));
768 }
769 // Save or discard the right-hand value as needed.
770 Visit(right);
771 ASSERT_EQ(context, right->context());
772
773 __ bind(&done);
774 }
775 862
776 863
777 } } // namespace v8::internal 864 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698