| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-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 1490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1501 // CompareStub and the inline code both support all values of cc. | 1501 // CompareStub and the inline code both support all values of cc. |
| 1502 } | 1502 } |
| 1503 // Implement comparison against a constant Smi, inlining the case | 1503 // Implement comparison against a constant Smi, inlining the case |
| 1504 // where both sides are Smis. | 1504 // where both sides are Smis. |
| 1505 left_side.ToRegister(); | 1505 left_side.ToRegister(); |
| 1506 ASSERT(left_side.is_valid()); | 1506 ASSERT(left_side.is_valid()); |
| 1507 JumpTarget is_smi(this); | 1507 JumpTarget is_smi(this); |
| 1508 __ test(left_side.reg(), Immediate(kSmiTagMask)); | 1508 __ test(left_side.reg(), Immediate(kSmiTagMask)); |
| 1509 is_smi.Branch(zero, &left_side, &right_side, taken); | 1509 is_smi.Branch(zero, &left_side, &right_side, taken); |
| 1510 | 1510 |
| 1511 // Setup and call the compare stub, which expects arguments in edx | 1511 // Setup and call the compare stub, which expects its arguments |
| 1512 // and eax. | 1512 // in registers. |
| 1513 CompareStub stub(cc, strict); | 1513 CompareStub stub(cc, strict); |
| 1514 left_side.ToRegister(edx); // Only left_side currently uses a register. | 1514 Result result = frame_->CallStub(&stub, &left_side, &right_side); |
| 1515 right_side.ToRegister(eax); // left_side is not in eax. eax is free. | |
| 1516 Result result = frame_->CallStub(&stub, &left_side, &right_side, 0); | |
| 1517 result.ToRegister(); | 1515 result.ToRegister(); |
| 1518 __ cmp(result.reg(), 0); | 1516 __ cmp(result.reg(), 0); |
| 1519 result.Unuse(); | 1517 result.Unuse(); |
| 1520 dest->true_target()->Branch(cc); | 1518 dest->true_target()->Branch(cc); |
| 1521 dest->false_target()->Jump(); | 1519 dest->false_target()->Jump(); |
| 1522 | 1520 |
| 1523 is_smi.Bind(&left_side, &right_side); | 1521 is_smi.Bind(&left_side, &right_side); |
| 1524 left_side.ToRegister(); | 1522 left_side.ToRegister(); |
| 1525 // Test smi equality and comparison by signed int comparison. | 1523 // Test smi equality and comparison by signed int comparison. |
| 1526 if (IsUnsafeSmi(right_side.handle())) { | 1524 if (IsUnsafeSmi(right_side.handle())) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1581 if (!known_non_smi) { | 1579 if (!known_non_smi) { |
| 1582 // Check for the smi case. | 1580 // Check for the smi case. |
| 1583 Result temp = allocator_->Allocate(); | 1581 Result temp = allocator_->Allocate(); |
| 1584 ASSERT(temp.is_valid()); | 1582 ASSERT(temp.is_valid()); |
| 1585 __ mov(temp.reg(), left_side.reg()); | 1583 __ mov(temp.reg(), left_side.reg()); |
| 1586 __ or_(temp.reg(), Operand(right_side.reg())); | 1584 __ or_(temp.reg(), Operand(right_side.reg())); |
| 1587 __ test(temp.reg(), Immediate(kSmiTagMask)); | 1585 __ test(temp.reg(), Immediate(kSmiTagMask)); |
| 1588 temp.Unuse(); | 1586 temp.Unuse(); |
| 1589 is_smi.Branch(zero, &left_side, &right_side, taken); | 1587 is_smi.Branch(zero, &left_side, &right_side, taken); |
| 1590 } | 1588 } |
| 1591 // When non-smi, call out to the compare stub. "parameters" setup by | 1589 // When non-smi, call out to the compare stub, which expects its |
| 1592 // calling code in edx and eax and "result" is returned in the flags. | 1590 // arguments in registers. |
| 1593 if (!left_side.reg().is(eax)) { | |
| 1594 right_side.ToRegister(eax); | |
| 1595 left_side.ToRegister(edx); | |
| 1596 } else if (!right_side.reg().is(edx)) { | |
| 1597 left_side.ToRegister(edx); | |
| 1598 right_side.ToRegister(eax); | |
| 1599 } else { | |
| 1600 frame_->Spill(eax); // Can be multiply referenced, even now. | |
| 1601 frame_->Spill(edx); | |
| 1602 __ xchg(eax, edx); | |
| 1603 // If left_side and right_side become real (non-dummy) arguments | |
| 1604 // to CallStub, they need to be swapped in this case. | |
| 1605 } | |
| 1606 CompareStub stub(cc, strict); | 1591 CompareStub stub(cc, strict); |
| 1607 Result answer = frame_->CallStub(&stub, &right_side, &left_side, 0); | 1592 Result answer = frame_->CallStub(&stub, &left_side, &right_side); |
| 1608 if (cc == equal) { | 1593 if (cc == equal) { |
| 1609 __ test(answer.reg(), Operand(answer.reg())); | 1594 __ test(answer.reg(), Operand(answer.reg())); |
| 1610 } else { | 1595 } else { |
| 1611 __ cmp(answer.reg(), 0); | 1596 __ cmp(answer.reg(), 0); |
| 1612 } | 1597 } |
| 1613 answer.Unuse(); | 1598 answer.Unuse(); |
| 1614 if (known_non_smi) { | 1599 if (known_non_smi) { |
| 1615 dest->Split(cc); | 1600 dest->Split(cc); |
| 1616 } else { | 1601 } else { |
| 1617 dest->true_target()->Branch(cc); | 1602 dest->true_target()->Branch(cc); |
| (...skipping 2767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4385 // Check if the object is a JS array or not. | 4370 // Check if the object is a JS array or not. |
| 4386 __ CmpObjectType(value.reg(), JS_ARRAY_TYPE, temp.reg()); | 4371 __ CmpObjectType(value.reg(), JS_ARRAY_TYPE, temp.reg()); |
| 4387 value.Unuse(); | 4372 value.Unuse(); |
| 4388 temp.Unuse(); | 4373 temp.Unuse(); |
| 4389 destination()->Split(equal); | 4374 destination()->Split(equal); |
| 4390 } | 4375 } |
| 4391 | 4376 |
| 4392 | 4377 |
| 4393 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { | 4378 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { |
| 4394 ASSERT(args->length() == 0); | 4379 ASSERT(args->length() == 0); |
| 4395 Result initial_value = allocator()->Allocate(eax); | |
| 4396 ASSERT(initial_value.is_valid()); | |
| 4397 __ Set(initial_value.reg(), | |
| 4398 Immediate(Smi::FromInt(scope_->num_parameters()))); | |
| 4399 // ArgumentsAccessStub takes the parameter count as an input argument | 4380 // ArgumentsAccessStub takes the parameter count as an input argument |
| 4400 // in register eax. | 4381 // in register eax. Create a constant result for it. |
| 4382 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())), this); |
| 4401 // Call the shared stub to get to the arguments.length. | 4383 // Call the shared stub to get to the arguments.length. |
| 4402 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); | 4384 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); |
| 4403 Result result = frame_->CallStub(&stub, &initial_value, 0); | 4385 Result result = frame_->CallStub(&stub, &count); |
| 4404 frame_->Push(&result); | 4386 frame_->Push(&result); |
| 4405 } | 4387 } |
| 4406 | 4388 |
| 4407 | 4389 |
| 4408 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { | 4390 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { |
| 4409 ASSERT(args->length() == 1); | 4391 ASSERT(args->length() == 1); |
| 4410 JumpTarget leave(this); | 4392 JumpTarget leave(this); |
| 4411 Load(args->at(0)); // Load the object. | 4393 Load(args->at(0)); // Load the object. |
| 4412 frame_->Dup(); | 4394 frame_->Dup(); |
| 4413 Result object = frame_->Pop(); | 4395 Result object = frame_->Pop(); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4468 | 4450 |
| 4469 // Leave. | 4451 // Leave. |
| 4470 leave.Bind(&value); | 4452 leave.Bind(&value); |
| 4471 frame_->Push(&value); | 4453 frame_->Push(&value); |
| 4472 } | 4454 } |
| 4473 | 4455 |
| 4474 | 4456 |
| 4475 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { | 4457 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { |
| 4476 ASSERT(args->length() == 1); | 4458 ASSERT(args->length() == 1); |
| 4477 | 4459 |
| 4478 // Load the key into edx and set eax to the formal parameters count | 4460 // ArgumentsAccessStub expects the key in edx and the formal |
| 4479 // for the currently executing function. | 4461 // parameter count in eax. |
| 4480 Load(args->at(0)); | 4462 Load(args->at(0)); |
| 4481 Result key = frame_->Pop(); | 4463 Result key = frame_->Pop(); |
| 4482 key.ToRegister(edx); | 4464 // Explicitly create a constant result. |
| 4483 | 4465 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters())), this); |
| 4484 Result parameters_count = allocator()->Allocate(eax); | |
| 4485 ASSERT(parameters_count.is_valid()); | |
| 4486 __ Set(parameters_count.reg(), | |
| 4487 Immediate(Smi::FromInt(scope_->num_parameters()))); | |
| 4488 | |
| 4489 // Call the shared stub to get to arguments[key]. | 4466 // Call the shared stub to get to arguments[key]. |
| 4490 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); | 4467 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); |
| 4491 Result result = frame_->CallStub(&stub, ¶meters_count, &key, 0); | 4468 Result result = frame_->CallStub(&stub, &key, &count); |
| 4492 frame_->Push(&result); | 4469 frame_->Push(&result); |
| 4493 } | 4470 } |
| 4494 | 4471 |
| 4495 | 4472 |
| 4496 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | 4473 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { |
| 4497 ASSERT(args->length() == 2); | 4474 ASSERT(args->length() == 2); |
| 4498 | 4475 |
| 4499 // Load the two objects into registers and perform the comparison. | 4476 // Load the two objects into registers and perform the comparison. |
| 4500 Load(args->at(0)); | 4477 Load(args->at(0)); |
| 4501 Load(args->at(1)); | 4478 Load(args->at(1)); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4640 case Token::NOT: | 4617 case Token::NOT: |
| 4641 case Token::DELETE: | 4618 case Token::DELETE: |
| 4642 case Token::TYPEOF: | 4619 case Token::TYPEOF: |
| 4643 UNREACHABLE(); // handled above | 4620 UNREACHABLE(); // handled above |
| 4644 break; | 4621 break; |
| 4645 | 4622 |
| 4646 case Token::SUB: { | 4623 case Token::SUB: { |
| 4647 UnarySubStub stub; | 4624 UnarySubStub stub; |
| 4648 // TODO(1222589): remove dependency of TOS being cached inside stub | 4625 // TODO(1222589): remove dependency of TOS being cached inside stub |
| 4649 Result operand = frame_->Pop(); | 4626 Result operand = frame_->Pop(); |
| 4650 operand.ToRegister(eax); | 4627 Result answer = frame_->CallStub(&stub, &operand); |
| 4651 Result answer = frame_->CallStub(&stub, &operand, 0); | |
| 4652 frame_->Push(&answer); | 4628 frame_->Push(&answer); |
| 4653 break; | 4629 break; |
| 4654 } | 4630 } |
| 4655 | 4631 |
| 4656 case Token::BIT_NOT: { | 4632 case Token::BIT_NOT: { |
| 4657 // Smi check. | 4633 // Smi check. |
| 4658 JumpTarget smi_label(this); | 4634 JumpTarget smi_label(this); |
| 4659 JumpTarget continue_label(this); | 4635 JumpTarget continue_label(this); |
| 4660 Result operand = frame_->Pop(); | 4636 Result operand = frame_->Pop(); |
| 4661 operand.ToRegister(); | 4637 operand.ToRegister(); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4774 } | 4750 } |
| 4775 #endif | 4751 #endif |
| 4776 }; | 4752 }; |
| 4777 | 4753 |
| 4778 | 4754 |
| 4779 void DeferredCountOperation::Generate() { | 4755 void DeferredCountOperation::Generate() { |
| 4780 CodeGenerator* cgen = generator(); | 4756 CodeGenerator* cgen = generator(); |
| 4781 | 4757 |
| 4782 Result value(cgen); | 4758 Result value(cgen); |
| 4783 enter()->Bind(&value); | 4759 enter()->Bind(&value); |
| 4784 value.ToRegister(eax); // The stubs below expect their argument in eax. | |
| 4785 | |
| 4786 if (is_postfix_) { | 4760 if (is_postfix_) { |
| 4787 RevertToNumberStub to_number_stub(is_increment_); | 4761 RevertToNumberStub to_number_stub(is_increment_); |
| 4788 value = generator()->frame()->CallStub(&to_number_stub, &value, 0); | 4762 value = generator()->frame()->CallStub(&to_number_stub, &value); |
| 4789 } | 4763 } |
| 4790 | 4764 |
| 4791 CounterOpStub stub(result_offset_, is_postfix_, is_increment_); | 4765 CounterOpStub stub(result_offset_, is_postfix_, is_increment_); |
| 4792 value = generator()->frame()->CallStub(&stub, &value, 0); | 4766 value = generator()->frame()->CallStub(&stub, &value); |
| 4793 exit_.Jump(&value); | 4767 exit_.Jump(&value); |
| 4794 } | 4768 } |
| 4795 | 4769 |
| 4796 | 4770 |
| 4797 void CodeGenerator::VisitCountOperation(CountOperation* node) { | 4771 void CodeGenerator::VisitCountOperation(CountOperation* node) { |
| 4798 Comment cmnt(masm_, "[ CountOperation"); | 4772 Comment cmnt(masm_, "[ CountOperation"); |
| 4799 | 4773 |
| 4800 bool is_postfix = node->is_postfix(); | 4774 bool is_postfix = node->is_postfix(); |
| 4801 bool is_increment = node->op() == Token::INC; | 4775 bool is_increment = node->op() == Token::INC; |
| 4802 | 4776 |
| (...skipping 2291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7094 | 7068 |
| 7095 // Slow-case: Go through the JavaScript implementation. | 7069 // Slow-case: Go through the JavaScript implementation. |
| 7096 __ bind(&slow); | 7070 __ bind(&slow); |
| 7097 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 7071 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 7098 } | 7072 } |
| 7099 | 7073 |
| 7100 | 7074 |
| 7101 #undef __ | 7075 #undef __ |
| 7102 | 7076 |
| 7103 } } // namespace v8::internal | 7077 } } // namespace v8::internal |
| OLD | NEW |