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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 Comment cmnt(masm_, "[ ExpressionStatement"); | 137 Comment cmnt(masm_, "[ ExpressionStatement"); |
138 SetStatementPosition(stmt); | 138 SetStatementPosition(stmt); |
139 Visit(stmt->expression()); | 139 Visit(stmt->expression()); |
140 } | 140 } |
141 | 141 |
142 | 142 |
143 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 143 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
144 Comment cmnt(masm_, "[ ReturnStatement"); | 144 Comment cmnt(masm_, "[ ReturnStatement"); |
145 SetStatementPosition(stmt); | 145 SetStatementPosition(stmt); |
146 Expression* expr = stmt->expression(); | 146 Expression* expr = stmt->expression(); |
147 Visit(expr); | 147 // Complete the statement based on the type of the subexpression. |
148 if (expr->AsLiteral() != NULL) { | |
149 __ Move(rax, expr->AsLiteral()->handle()); | |
150 } else { | |
151 Visit(expr); | |
152 ASSERT(expr->location().is_temporary()); | |
153 __ pop(rax); | |
154 } | |
148 | 155 |
149 // Complete the statement based on the location of the subexpression. | |
150 Location source = expr->location(); | |
151 ASSERT(!source.is_nowhere()); | |
152 if (source.is_temporary()) { | |
153 __ pop(rax); | |
154 } else { | |
155 ASSERT(source.is_constant()); | |
156 ASSERT(expr->AsLiteral() != NULL); | |
157 __ Move(rax, expr->AsLiteral()->handle()); | |
158 } | |
159 if (FLAG_trace) { | 156 if (FLAG_trace) { |
160 __ push(rax); | 157 __ push(rax); |
161 __ CallRuntime(Runtime::kTraceExit, 1); | 158 __ CallRuntime(Runtime::kTraceExit, 1); |
162 } | 159 } |
163 | 160 |
164 __ RecordJSReturn(); | 161 __ RecordJSReturn(); |
165 // Do not use the leave instruction here because it is too short to | 162 // Do not use the leave instruction here because it is too short to |
166 // patch with the code required by the debugger. | 163 // patch with the code required by the debugger. |
167 __ movq(rsp, rbp); | 164 __ movq(rsp, rbp); |
168 __ pop(rbp); | 165 __ pop(rbp); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
230 ASSERT(slot != NULL); | 227 ASSERT(slot != NULL); |
231 if (expr->location().is_temporary()) { | 228 if (expr->location().is_temporary()) { |
232 __ push(Operand(rbp, SlotOffset(slot))); | 229 __ push(Operand(rbp, SlotOffset(slot))); |
233 } else { | 230 } else { |
234 ASSERT(expr->location().is_nowhere()); | 231 ASSERT(expr->location().is_nowhere()); |
235 } | 232 } |
236 } | 233 } |
237 } | 234 } |
238 | 235 |
239 | 236 |
237 void FastCodeGenerator::VisitLiteral(Literal* expr) { | |
238 if (expr->location().is_temporary()) { | |
239 __ Push(expr->handle()); | |
240 } else { | |
241 ASSERT(expr->location().is_nowhere()); | |
242 } | |
243 } | |
244 | |
245 | |
240 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 246 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
241 Comment cmnt(masm_, "[ ObjectLiteral"); | 247 Comment cmnt(masm_, "[ ObjectLiteral"); |
242 Label boilerplate_exists; | 248 Label boilerplate_exists; |
243 | 249 |
244 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 250 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
245 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 251 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
246 int literal_offset = | 252 int literal_offset = |
247 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 253 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
248 __ movq(rax, FieldOperand(rbx, literal_offset)); | 254 __ movq(rax, FieldOperand(rbx, literal_offset)); |
249 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 255 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
294 __ Move(rcx, key->handle()); | 300 __ Move(rcx, key->handle()); |
295 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 301 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
296 __ call(ic, RelocInfo::CODE_TARGET); | 302 __ call(ic, RelocInfo::CODE_TARGET); |
297 // StoreIC leaves the receiver on the stack. | 303 // StoreIC leaves the receiver on the stack. |
298 break; | 304 break; |
299 } | 305 } |
300 // fall through | 306 // fall through |
301 case ObjectLiteral::Property::PROTOTYPE: | 307 case ObjectLiteral::Property::PROTOTYPE: |
302 __ push(rax); | 308 __ push(rax); |
303 Visit(key); | 309 Visit(key); |
304 if (key->location().is_constant()) { | 310 ASSERT(key->location().is_temporary()); |
305 __ Push(key->handle()); | |
306 } | |
307 Visit(value); | 311 Visit(value); |
308 ASSERT(value->location().is_temporary()); | 312 ASSERT(value->location().is_temporary()); |
309 __ CallRuntime(Runtime::kSetProperty, 3); | 313 __ CallRuntime(Runtime::kSetProperty, 3); |
310 __ movq(rax, Operand(rsp, 0)); // Restore result into rax. | 314 __ movq(rax, Operand(rsp, 0)); // Restore result into rax. |
311 break; | 315 break; |
312 case ObjectLiteral::Property::SETTER: // fall through | 316 case ObjectLiteral::Property::SETTER: // fall through |
313 case ObjectLiteral::Property::GETTER: | 317 case ObjectLiteral::Property::GETTER: |
314 __ push(rax); | 318 __ push(rax); |
315 Visit(key); | 319 Visit(key); |
316 if (key->location().is_constant()) { | 320 ASSERT(key->location.is_temporary()); |
317 __ Push(key->handle()); | |
318 } | |
319 __ Push(property->kind() == ObjectLiteral::Property::SETTER ? | 321 __ Push(property->kind() == ObjectLiteral::Property::SETTER ? |
320 Smi::FromInt(1) : | 322 Smi::FromInt(1) : |
321 Smi::FromInt(0)); | 323 Smi::FromInt(0)); |
322 Visit(value); | 324 Visit(value); |
323 ASSERT(value->location().is_temporary()); | 325 ASSERT(value->location().is_temporary()); |
324 __ CallRuntime(Runtime::kDefineAccessor, 4); | 326 __ CallRuntime(Runtime::kDefineAccessor, 4); |
325 __ movq(rax, Operand(rsp, 0)); // Restore result into rax. | 327 __ movq(rax, Operand(rsp, 0)); // Restore result into rax. |
326 break; | 328 break; |
327 default: UNREACHABLE(); | 329 default: UNREACHABLE(); |
328 } | 330 } |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
432 __ addq(rsp, Immediate(kPointerSize)); | 434 __ addq(rsp, Immediate(kPointerSize)); |
433 } else if (destination.is_temporary() && !result_saved) { | 435 } else if (destination.is_temporary() && !result_saved) { |
434 __ push(rax); | 436 __ push(rax); |
435 } | 437 } |
436 } | 438 } |
437 | 439 |
438 | 440 |
439 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 441 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
440 Comment cmnt(masm_, "[ Assignment"); | 442 Comment cmnt(masm_, "[ Assignment"); |
441 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 443 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); |
442 Expression* rhs = expr->value(); | |
443 Visit(rhs); | |
444 | 444 |
445 // Left-hand side can only be a global or a (parameter or local) slot. | 445 // Left-hand side can only be a global or a (parameter or local) slot. |
446 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 446 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
447 ASSERT(var != NULL); | 447 ASSERT(var != NULL); |
448 ASSERT(var->is_global() || var->slot() != NULL); | 448 ASSERT(var->is_global() || var->slot() != NULL); |
449 | 449 |
450 // Complete the assignment based on the location of the right-hand-side | 450 Expression* rhs = expr->value(); |
451 // value and the desired location of the assignment value. | |
452 Location destination = expr->location(); | 451 Location destination = expr->location(); |
453 Location source = rhs->location(); | |
454 ASSERT(!destination.is_constant()); | |
455 ASSERT(!source.is_nowhere()); | |
456 | |
457 if (var->is_global()) { | 452 if (var->is_global()) { |
458 // Assignment to a global variable, use inline caching. Right-hand-side | 453 // Assignment to a global variable, use inline caching. Right-hand-side |
459 // value is passed in rax, variable name in rcx, and the global object | 454 // value is passed in rax, variable name in rcx, and the global object |
460 // on the stack. | 455 // on the stack. |
461 if (source.is_temporary()) { | 456 |
457 // Code for the right-hand-side expression depends on its type. | |
458 if (rhs->AsLiteral() != NULL) { | |
459 __ Move(rax, rhs->AsLiteral()->handle()); | |
460 } else { | |
461 ASSERT(rhs->location().is_temporary()); | |
462 Visit(rhs); | |
462 __ pop(rax); | 463 __ pop(rax); |
463 } else { | |
464 ASSERT(source.is_constant()); | |
465 ASSERT(rhs->AsLiteral() != NULL); | |
466 __ Move(rax, rhs->AsLiteral()->handle()); | |
467 } | 464 } |
468 __ Move(rcx, var->name()); | 465 __ Move(rcx, var->name()); |
469 __ push(CodeGenerator::GlobalObject()); | 466 __ push(CodeGenerator::GlobalObject()); |
470 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 467 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
471 __ Call(ic, RelocInfo::CODE_TARGET); | 468 __ Call(ic, RelocInfo::CODE_TARGET); |
472 // Overwrite the global object on the stack with the result if needed. | 469 // Overwrite the global object on the stack with the result if needed. |
473 if (destination.is_temporary()) { | 470 if (destination.is_temporary()) { |
474 __ movq(Operand(rsp, 0), rax); | 471 __ movq(Operand(rsp, 0), rax); |
475 } else { | 472 } else { |
476 __ addq(rsp, Immediate(kPointerSize)); | 473 __ addq(rsp, Immediate(kPointerSize)); |
477 } | 474 } |
478 } else { | 475 } else { |
479 if (source.is_temporary()) { | 476 // Local or parameter assignment. |
477 | |
478 // Code for the right-hand-side expression depends on its type. | |
479 if (rhs->AsLiteral() != NULL) { | |
480 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a | |
481 // discarded result. Always perform the assignment. | |
482 __ Move(kScratchRegister, rhs->AsLiteral()->handle()); | |
483 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); | |
484 if (destination.is_temporary()) { | |
485 // Case 'temp <- (var = constant)'. Save result. | |
486 __ push(kScratchRegister); | |
487 } | |
fschneider
2009/10/26 17:57:20
Add an assert here to be consistent with the rest
| |
488 } else { | |
489 ASSERT(rhs->location().is_temporary()); | |
490 Visit(rhs); | |
480 if (destination.is_temporary()) { | 491 if (destination.is_temporary()) { |
481 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side temporary | 492 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side temporary |
482 // on the stack. | 493 // on the stack. |
483 __ movq(kScratchRegister, Operand(rsp, 0)); | 494 __ movq(kScratchRegister, Operand(rsp, 0)); |
484 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); | 495 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); |
485 } else { | 496 } else { |
486 ASSERT(destination.is_nowhere()); | 497 ASSERT(destination.is_nowhere()); |
487 // Case 'var = temp'. Discard right-hand-side temporary. | 498 // Case 'var = temp'. Discard right-hand-side temporary. |
488 __ pop(Operand(rbp, SlotOffset(var->slot()))); | 499 __ pop(Operand(rbp, SlotOffset(var->slot()))); |
489 } | 500 } |
490 } else { | |
491 ASSERT(source.is_constant()); | |
492 ASSERT(rhs->AsLiteral() != NULL); | |
493 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a | |
494 // discarded result. Always perform the assignment. | |
495 __ Move(kScratchRegister, rhs->AsLiteral()->handle()); | |
496 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); | |
497 if (destination.is_temporary()) { | |
498 // Case 'temp <- (var = constant)'. Save result. | |
499 __ push(kScratchRegister); | |
500 } | |
501 } | 501 } |
502 } | 502 } |
503 } | 503 } |
504 | 504 |
505 | 505 |
506 void FastCodeGenerator::VisitCall(Call* expr) { | 506 void FastCodeGenerator::VisitCall(Call* expr) { |
507 Expression* fun = expr->expression(); | 507 Expression* fun = expr->expression(); |
508 ZoneList<Expression*>* args = expr->arguments(); | 508 ZoneList<Expression*>* args = expr->arguments(); |
509 Variable* var = fun->AsVariableProxy()->AsVariable(); | 509 Variable* var = fun->AsVariableProxy()->AsVariable(); |
510 ASSERT(var != NULL && !var->is_this() && var->is_global()); | 510 ASSERT(var != NULL && !var->is_this() && var->is_global()); |
511 ASSERT(!var->is_possibly_eval()); | 511 ASSERT(!var->is_possibly_eval()); |
512 | 512 |
513 __ Push(var->name()); | 513 __ Push(var->name()); |
514 // Push global object (receiver). | 514 // Push global object (receiver). |
515 __ push(CodeGenerator::GlobalObject()); | 515 __ push(CodeGenerator::GlobalObject()); |
516 int arg_count = args->length(); | 516 int arg_count = args->length(); |
517 for (int i = 0; i < arg_count; i++) { | 517 for (int i = 0; i < arg_count; i++) { |
518 Visit(args->at(i)); | 518 Visit(args->at(i)); |
519 ASSERT(!args->at(i)->location().is_nowhere()); | 519 ASSERT(args->at(i)->location().is_temporary()); |
520 if (args->at(i)->location().is_constant()) { | |
521 ASSERT(args->at(i)->AsLiteral() != NULL); | |
522 __ Push(args->at(i)->AsLiteral()->handle()); | |
523 } | |
524 } | 520 } |
525 // Record source position for debugger | 521 // Record source position for debugger |
526 SetSourcePosition(expr->position()); | 522 SetSourcePosition(expr->position()); |
527 // Call the IC initialization code. | 523 // Call the IC initialization code. |
528 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 524 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
529 NOT_IN_LOOP); | 525 NOT_IN_LOOP); |
530 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 526 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
531 // Restore context register. | 527 // Restore context register. |
532 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 528 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
533 // Discard the function left on TOS. | 529 // Discard the function left on TOS. |
(...skipping 10 matching lines...) Expand all Loading... | |
544 Comment cmnt(masm_, "[ CallRuntime"); | 540 Comment cmnt(masm_, "[ CallRuntime"); |
545 ZoneList<Expression*>* args = expr->arguments(); | 541 ZoneList<Expression*>* args = expr->arguments(); |
546 Runtime::Function* function = expr->function(); | 542 Runtime::Function* function = expr->function(); |
547 | 543 |
548 ASSERT(function != NULL); | 544 ASSERT(function != NULL); |
549 | 545 |
550 // Push the arguments ("left-to-right"). | 546 // Push the arguments ("left-to-right"). |
551 int arg_count = args->length(); | 547 int arg_count = args->length(); |
552 for (int i = 0; i < arg_count; i++) { | 548 for (int i = 0; i < arg_count; i++) { |
553 Visit(args->at(i)); | 549 Visit(args->at(i)); |
554 ASSERT(!args->at(i)->location().is_nowhere()); | 550 ASSERT(args->at(i)->location().is_temporary()); |
555 if (args->at(i)->location().is_constant()) { | |
556 ASSERT(args->at(i)->AsLiteral() != NULL); | |
557 __ Push(args->at(i)->AsLiteral()->handle()); | |
558 } else { | |
559 ASSERT(args->at(i)->location().is_temporary()); | |
560 // If location is temporary, it is already on the stack, | |
561 // so nothing to do here. | |
562 } | |
563 } | 551 } |
564 | 552 |
565 __ CallRuntime(function, arg_count); | 553 __ CallRuntime(function, arg_count); |
566 if (expr->location().is_temporary()) { | 554 if (expr->location().is_temporary()) { |
567 __ push(rax); | 555 __ push(rax); |
568 } else { | 556 } else { |
569 ASSERT(expr->location().is_nowhere()); | 557 ASSERT(expr->location().is_nowhere()); |
570 } | 558 } |
571 } | 559 } |
572 | 560 |
573 | 561 |
574 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 562 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
575 // Compile a short-circuited boolean or operation in a non-test | 563 // Compile a short-circuited boolean or operation in a non-test |
576 // context. | 564 // context. |
577 ASSERT(expr->op() == Token::OR); | 565 ASSERT(expr->op() == Token::OR); |
578 // Compile (e0 || e1) as if it were | 566 // Compile (e0 || e1) as if it were |
579 // (let (temp = e0) temp ? temp : e1). | 567 // (let (temp = e0) temp ? temp : e1). |
580 | 568 |
581 Label eval_right, done; | 569 Label eval_right, done; |
582 Location destination = expr->location(); | 570 Location destination = expr->location(); |
583 ASSERT(!destination.is_constant()); | 571 Expression* left = expr->left(); |
572 Expression* right = expr->right(); | |
584 | 573 |
585 Expression* left = expr->left(); | |
586 Location left_source = left->location(); | |
587 ASSERT(!left_source.is_nowhere()); | |
588 | |
589 Expression* right = expr->right(); | |
590 Location right_source = right->location(); | |
591 ASSERT(!right_source.is_nowhere()); | |
592 | |
593 Visit(left); | |
594 // Use the shared ToBoolean stub to find the boolean value of the | 574 // Use the shared ToBoolean stub to find the boolean value of the |
595 // left-hand subexpression. Load the value into rax to perform some | 575 // left-hand subexpression. Load the value into rax to perform some |
596 // inlined checks assumed by the stub. | 576 // inlined checks assumed by the stub. |
597 if (left_source.is_temporary()) { | 577 |
578 // Compile the left-hand value into rax. Put it on the stack if we may | |
579 // need it as the value of the whole expression. | |
580 if (left->AsLiteral() != NULL) { | |
581 __ Move(rax, left->AsLiteral()->handle()); | |
582 if (destination.is_temporary()) __ push(rax); | |
fschneider
2009/10/26 17:57:20
May want to add an assert here to be consistent wi
| |
583 } else { | |
584 Visit(left); | |
585 ASSERT(left->location().is_temporary()); | |
598 if (destination.is_temporary()) { | 586 if (destination.is_temporary()) { |
599 // Copy the left-hand value into rax because we may need it as the | 587 // Copy the left-hand value into rax because we may need it as the |
600 // final result. | 588 // final result. |
601 __ movq(rax, Operand(rsp, 0)); | 589 __ movq(rax, Operand(rsp, 0)); |
602 } else { | 590 } else { |
603 // Pop the left-hand value into rax because we will not need it as the | 591 // Pop the left-hand value into rax because we will not need it as the |
604 // final result. | 592 // final result. |
605 __ pop(rax); | 593 __ pop(rax); |
fschneider
2009/10/26 17:57:20
Adding an assert to be consistent on all platforms
| |
606 } | 594 } |
607 } else { | |
608 // Load the left-hand value into rax. Put it on the stack if we may | |
609 // need it. | |
610 ASSERT(left->AsLiteral() != NULL); | |
611 __ Move(rax, left->AsLiteral()->handle()); | |
612 if (destination.is_temporary()) __ push(rax); | |
613 } | 595 } |
614 // The left-hand value is in rax. It is also on the stack iff the | 596 // The left-hand value is in rax. It is also on the stack iff the |
615 // destination location is temporary. | 597 // destination location is temporary. |
616 | 598 |
617 // Perform fast checks assumed by the stub. | 599 // Perform fast checks assumed by the stub. |
618 // The undefined value is false. | 600 // The undefined value is false. |
619 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 601 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
620 __ j(equal, &eval_right); | 602 __ j(equal, &eval_right); |
621 __ CompareRoot(rax, Heap::kTrueValueRootIndex); // True is true. | 603 __ CompareRoot(rax, Heap::kTrueValueRootIndex); // True is true. |
622 __ j(equal, &done); | 604 __ j(equal, &done); |
(...skipping 10 matching lines...) Expand all Loading... | |
633 ToBooleanStub stub; | 615 ToBooleanStub stub; |
634 __ CallStub(&stub); | 616 __ CallStub(&stub); |
635 __ testq(rax, rax); // The stub returns nonzero for true. | 617 __ testq(rax, rax); // The stub returns nonzero for true. |
636 __ j(not_zero, &done); | 618 __ j(not_zero, &done); |
637 | 619 |
638 __ bind(&eval_right); | 620 __ bind(&eval_right); |
639 // Discard the left-hand value if present on the stack. | 621 // Discard the left-hand value if present on the stack. |
640 if (destination.is_temporary()) { | 622 if (destination.is_temporary()) { |
641 __ addq(rsp, Immediate(kPointerSize)); | 623 __ addq(rsp, Immediate(kPointerSize)); |
642 } | 624 } |
643 Visit(right); | |
644 | |
645 // Save or discard the right-hand value as needed. | 625 // Save or discard the right-hand value as needed. |
646 if (destination.is_temporary() && right_source.is_constant()) { | 626 if (right->AsLiteral() != NULL) { |
647 ASSERT(right->AsLiteral() != NULL); | 627 if (destination.is_temporary()) { |
648 __ Push(right->AsLiteral()->handle()); | 628 __ Push(right->AsLiteral()->handle()); |
649 } else if (destination.is_nowhere() && right_source.is_temporary()) { | 629 } else { |
650 __ addq(rsp, Immediate(kPointerSize)); | 630 ASSERT(destination.is_nowhere()); |
631 } | |
632 } else { | |
633 Visit(right); | |
634 ASSERT(right->location().is_temporary()); | |
635 if (destination.is_nowhere()) { | |
636 __ addq(rsp, Immediate(kPointerSize)); | |
637 } else { | |
638 ASSERT(destination.is_temporary()); | |
639 } | |
651 } | 640 } |
652 | 641 |
653 __ bind(&done); | 642 __ bind(&done); |
654 } | 643 } |
655 | 644 |
656 | 645 |
657 } } // namespace v8::internal | 646 } } // namespace v8::internal |
OLD | NEW |