OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 4466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4477 | 4477 |
4478 // Load the argument on the stack and jump to the runtime. | 4478 // Load the argument on the stack and jump to the runtime. |
4479 Load(args->at(0)); | 4479 Load(args->at(0)); |
4480 | 4480 |
4481 NumberToStringStub stub; | 4481 NumberToStringStub stub; |
4482 Result result = frame_->CallStub(&stub, 1); | 4482 Result result = frame_->CallStub(&stub, 1); |
4483 frame_->Push(&result); | 4483 frame_->Push(&result); |
4484 } | 4484 } |
4485 | 4485 |
4486 | 4486 |
| 4487 class DeferredSwapElements: public DeferredCode { |
| 4488 public: |
| 4489 DeferredSwapElements(Register object, Register index1, Register index2) |
| 4490 : object_(object), index1_(index1), index2_(index2) { |
| 4491 set_comment("[ DeferredSwapElements"); |
| 4492 } |
| 4493 |
| 4494 virtual void Generate(); |
| 4495 |
| 4496 private: |
| 4497 Register object_, index1_, index2_; |
| 4498 }; |
| 4499 |
| 4500 |
| 4501 void DeferredSwapElements::Generate() { |
| 4502 __ push(object_); |
| 4503 __ push(index1_); |
| 4504 __ push(index2_); |
| 4505 __ CallRuntime(Runtime::kSwapElements, 3); |
| 4506 } |
| 4507 |
| 4508 |
4487 void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) { | 4509 void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) { |
4488 Comment cmnt(masm_, "[ GenerateSwapElements"); | 4510 Comment cmnt(masm_, "[ GenerateSwapElements"); |
4489 | 4511 |
4490 ASSERT_EQ(3, args->length()); | 4512 ASSERT_EQ(3, args->length()); |
4491 | 4513 |
4492 Load(args->at(0)); | 4514 Load(args->at(0)); |
4493 Load(args->at(1)); | 4515 Load(args->at(1)); |
4494 Load(args->at(2)); | 4516 Load(args->at(2)); |
4495 | 4517 |
4496 Result result = frame_->CallRuntime(Runtime::kSwapElements, 3); | 4518 Result index2 = frame_->Pop(); |
4497 frame_->Push(&result); | 4519 index2.ToRegister(); |
| 4520 |
| 4521 Result index1 = frame_->Pop(); |
| 4522 index1.ToRegister(); |
| 4523 |
| 4524 Result object = frame_->Pop(); |
| 4525 object.ToRegister(); |
| 4526 |
| 4527 Result tmp1 = allocator()->Allocate(); |
| 4528 tmp1.ToRegister(); |
| 4529 Result tmp2 = allocator()->Allocate(); |
| 4530 tmp2.ToRegister(); |
| 4531 |
| 4532 frame_->Spill(object.reg()); |
| 4533 frame_->Spill(index1.reg()); |
| 4534 frame_->Spill(index2.reg()); |
| 4535 |
| 4536 DeferredSwapElements* deferred = new DeferredSwapElements(object.reg(), |
| 4537 index1.reg(), |
| 4538 index2.reg()); |
| 4539 |
| 4540 // Fetch the map and check if array is in fast case. |
| 4541 // Check that object doesn't require security checks and |
| 4542 // has no indexed interceptor. |
| 4543 __ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg()); |
| 4544 deferred->Branch(below); |
| 4545 __ testb(FieldOperand(tmp1.reg(), Map::kBitFieldOffset), |
| 4546 Immediate(KeyedLoadIC::kSlowCaseBitFieldMask)); |
| 4547 deferred->Branch(not_zero); |
| 4548 |
| 4549 // Check the object's elements are in fast case. |
| 4550 __ movq(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset)); |
| 4551 __ CompareRoot(FieldOperand(tmp1.reg(), HeapObject::kMapOffset), |
| 4552 Heap::kFixedArrayMapRootIndex); |
| 4553 deferred->Branch(not_equal); |
| 4554 |
| 4555 // Check that both indices are smis. |
| 4556 Condition both_smi = __ CheckBothSmi(index1.reg(), index2.reg()); |
| 4557 deferred->Branch(NegateCondition(both_smi)); |
| 4558 |
| 4559 // Bring addresses into index1 and index2. |
| 4560 __ SmiToInteger32(index1.reg(), index1.reg()); |
| 4561 __ lea(index1.reg(), FieldOperand(tmp1.reg(), |
| 4562 index1.reg(), |
| 4563 times_pointer_size, |
| 4564 FixedArray::kHeaderSize)); |
| 4565 __ SmiToInteger32(index2.reg(), index2.reg()); |
| 4566 __ lea(index2.reg(), FieldOperand(tmp1.reg(), |
| 4567 index2.reg(), |
| 4568 times_pointer_size, |
| 4569 FixedArray::kHeaderSize)); |
| 4570 |
| 4571 // Swap elements. |
| 4572 __ movq(object.reg(), Operand(index1.reg(), 0)); |
| 4573 __ movq(tmp2.reg(), Operand(index2.reg(), 0)); |
| 4574 __ movq(Operand(index2.reg(), 0), object.reg()); |
| 4575 __ movq(Operand(index1.reg(), 0), tmp2.reg()); |
| 4576 |
| 4577 Label done; |
| 4578 __ InNewSpace(tmp1.reg(), tmp2.reg(), equal, &done); |
| 4579 // Possible optimization: do a check that both values are Smis |
| 4580 // (or them and test against Smi mask.) |
| 4581 |
| 4582 __ movq(tmp2.reg(), tmp1.reg()); |
| 4583 RecordWriteStub recordWrite1(tmp2.reg(), index1.reg(), object.reg()); |
| 4584 __ CallStub(&recordWrite1); |
| 4585 |
| 4586 RecordWriteStub recordWrite2(tmp1.reg(), index2.reg(), object.reg()); |
| 4587 __ CallStub(&recordWrite2); |
| 4588 |
| 4589 __ bind(&done); |
| 4590 |
| 4591 deferred->BindExit(); |
| 4592 frame_->Push(Factory::undefined_value()); |
4498 } | 4593 } |
4499 | 4594 |
4500 | 4595 |
4501 void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) { | 4596 void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) { |
4502 Comment cmnt(masm_, "[ GenerateCallFunction"); | 4597 Comment cmnt(masm_, "[ GenerateCallFunction"); |
4503 | 4598 |
4504 ASSERT(args->length() >= 2); | 4599 ASSERT(args->length() >= 2); |
4505 | 4600 |
4506 int n_args = args->length() - 2; // for receiver and function. | 4601 int n_args = args->length() - 2; // for receiver and function. |
4507 Load(args->at(0)); // receiver | 4602 Load(args->at(0)); // receiver |
(...skipping 3621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8129 // Generate code to lookup number in the number string cache. | 8224 // Generate code to lookup number in the number string cache. |
8130 GenerateLookupNumberStringCache(masm, rbx, rax, r8, r9, false, &runtime); | 8225 GenerateLookupNumberStringCache(masm, rbx, rax, r8, r9, false, &runtime); |
8131 __ ret(1 * kPointerSize); | 8226 __ ret(1 * kPointerSize); |
8132 | 8227 |
8133 __ bind(&runtime); | 8228 __ bind(&runtime); |
8134 // Handle number to string in the runtime system if not found in the cache. | 8229 // Handle number to string in the runtime system if not found in the cache. |
8135 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); | 8230 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); |
8136 } | 8231 } |
8137 | 8232 |
8138 | 8233 |
| 8234 void RecordWriteStub::Generate(MacroAssembler* masm) { |
| 8235 masm->RecordWriteHelper(object_, addr_, scratch_); |
| 8236 masm->ret(0); |
| 8237 } |
| 8238 |
| 8239 |
8139 static int NegativeComparisonResult(Condition cc) { | 8240 static int NegativeComparisonResult(Condition cc) { |
8140 ASSERT(cc != equal); | 8241 ASSERT(cc != equal); |
8141 ASSERT((cc == less) || (cc == less_equal) | 8242 ASSERT((cc == less) || (cc == less_equal) |
8142 || (cc == greater) || (cc == greater_equal)); | 8243 || (cc == greater) || (cc == greater_equal)); |
8143 return (cc == greater || cc == greater_equal) ? LESS : GREATER; | 8244 return (cc == greater || cc == greater_equal) ? LESS : GREATER; |
8144 } | 8245 } |
8145 | 8246 |
8146 void CompareStub::Generate(MacroAssembler* masm) { | 8247 void CompareStub::Generate(MacroAssembler* masm) { |
8147 Label call_builtin, done; | 8248 Label call_builtin, done; |
8148 // The compare stub returns a positive, negative, or zero 64-bit integer | 8249 // The compare stub returns a positive, negative, or zero 64-bit integer |
(...skipping 2882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11031 // Call the function from C++. | 11132 // Call the function from C++. |
11032 return FUNCTION_CAST<ModuloFunction>(buffer); | 11133 return FUNCTION_CAST<ModuloFunction>(buffer); |
11033 } | 11134 } |
11034 | 11135 |
11035 #endif | 11136 #endif |
11036 | 11137 |
11037 | 11138 |
11038 #undef __ | 11139 #undef __ |
11039 | 11140 |
11040 } } // namespace v8::internal | 11141 } } // namespace v8::internal |
OLD | NEW |