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 |