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 8606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8617 frame_->SetElementAt(0, &answer); | 8617 frame_->SetElementAt(0, &answer); |
8618 } | 8618 } |
8619 | 8619 |
8620 | 8620 |
8621 void InstanceofStub::Generate(MacroAssembler* masm) { | 8621 void InstanceofStub::Generate(MacroAssembler* masm) { |
8622 // Implements "value instanceof function" operator. | 8622 // Implements "value instanceof function" operator. |
8623 // Expected input state: | 8623 // Expected input state: |
8624 // rsp[0] : return address | 8624 // rsp[0] : return address |
8625 // rsp[1] : function pointer | 8625 // rsp[1] : function pointer |
8626 // rsp[2] : value | 8626 // rsp[2] : value |
| 8627 // Returns a bitwise zero to indicate that the value |
| 8628 // is and instance of the function and anything else to |
| 8629 // indicate that the value is not an instance. |
8627 | 8630 |
8628 // Get the object - go slow case if it's a smi. | 8631 // Get the object - go slow case if it's a smi. |
8629 Label slow; | 8632 Label slow; |
8630 __ movq(rax, Operand(rsp, 2 * kPointerSize)); | 8633 __ movq(rax, Operand(rsp, 2 * kPointerSize)); |
8631 __ JumpIfSmi(rax, &slow); | 8634 __ JumpIfSmi(rax, &slow); |
8632 | 8635 |
8633 // Check that the left hand is a JS object. Leave its map in rax. | 8636 // Check that the left hand is a JS object. Leave its map in rax. |
8634 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax); | 8637 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rax); |
8635 __ j(below, &slow); | 8638 __ j(below, &slow); |
8636 __ CmpInstanceType(rax, LAST_JS_OBJECT_TYPE); | 8639 __ CmpInstanceType(rax, LAST_JS_OBJECT_TYPE); |
8637 __ j(above, &slow); | 8640 __ j(above, &slow); |
8638 | 8641 |
8639 // Get the prototype of the function. | 8642 // Get the prototype of the function. |
8640 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); | 8643 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); |
| 8644 // rdx is function, rax is map. |
| 8645 |
| 8646 // Look up the function and the map in the instanceof cache. |
| 8647 Label miss; |
| 8648 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); |
| 8649 __ j(not_equal, &miss); |
| 8650 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex); |
| 8651 __ j(not_equal, &miss); |
| 8652 __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); |
| 8653 __ ret(2 * kPointerSize); |
| 8654 |
| 8655 __ bind(&miss); |
8641 __ TryGetFunctionPrototype(rdx, rbx, &slow); | 8656 __ TryGetFunctionPrototype(rdx, rbx, &slow); |
8642 | 8657 |
8643 // Check that the function prototype is a JS object. | 8658 // Check that the function prototype is a JS object. |
8644 __ JumpIfSmi(rbx, &slow); | 8659 __ JumpIfSmi(rbx, &slow); |
8645 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, kScratchRegister); | 8660 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, kScratchRegister); |
8646 __ j(below, &slow); | 8661 __ j(below, &slow); |
8647 __ CmpInstanceType(kScratchRegister, LAST_JS_OBJECT_TYPE); | 8662 __ CmpInstanceType(kScratchRegister, LAST_JS_OBJECT_TYPE); |
8648 __ j(above, &slow); | 8663 __ j(above, &slow); |
8649 | 8664 |
8650 // Register mapping: rax is object map and rbx is function prototype. | 8665 // Register mapping: |
| 8666 // rax is object map. |
| 8667 // rdx is function. |
| 8668 // rbx is function prototype. |
| 8669 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); |
| 8670 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex); |
| 8671 |
8651 __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset)); | 8672 __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset)); |
8652 | 8673 |
8653 // Loop through the prototype chain looking for the function prototype. | 8674 // Loop through the prototype chain looking for the function prototype. |
8654 Label loop, is_instance, is_not_instance; | 8675 Label loop, is_instance, is_not_instance; |
8655 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex); | 8676 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex); |
8656 __ bind(&loop); | 8677 __ bind(&loop); |
8657 __ cmpq(rcx, rbx); | 8678 __ cmpq(rcx, rbx); |
8658 __ j(equal, &is_instance); | 8679 __ j(equal, &is_instance); |
8659 __ cmpq(rcx, kScratchRegister); | 8680 __ cmpq(rcx, kScratchRegister); |
| 8681 // The code at is_not_instance assumes that kScratchRegister contains a |
| 8682 // non-zero GCable value (the null object in this case). |
8660 __ j(equal, &is_not_instance); | 8683 __ j(equal, &is_not_instance); |
8661 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); | 8684 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); |
8662 __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset)); | 8685 __ movq(rcx, FieldOperand(rcx, Map::kPrototypeOffset)); |
8663 __ jmp(&loop); | 8686 __ jmp(&loop); |
8664 | 8687 |
8665 __ bind(&is_instance); | 8688 __ bind(&is_instance); |
8666 __ xorl(rax, rax); | 8689 __ xorl(rax, rax); |
| 8690 // Store bitwise zero in the cache. This is a Smi in GC terms. |
| 8691 ASSERT_EQ(0, kSmiTag); |
| 8692 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); |
8667 __ ret(2 * kPointerSize); | 8693 __ ret(2 * kPointerSize); |
8668 | 8694 |
8669 __ bind(&is_not_instance); | 8695 __ bind(&is_not_instance); |
8670 __ movl(rax, Immediate(1)); | 8696 // We have to store a non-zero value in the cache. |
| 8697 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); |
8671 __ ret(2 * kPointerSize); | 8698 __ ret(2 * kPointerSize); |
8672 | 8699 |
8673 // Slow-case: Go through the JavaScript implementation. | 8700 // Slow-case: Go through the JavaScript implementation. |
8674 __ bind(&slow); | 8701 __ bind(&slow); |
8675 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 8702 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
8676 } | 8703 } |
8677 | 8704 |
8678 | 8705 |
8679 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { | 8706 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { |
8680 // rsp[0] : return address | 8707 // rsp[0] : return address |
(...skipping 2554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11235 // Call the function from C++. | 11262 // Call the function from C++. |
11236 return FUNCTION_CAST<ModuloFunction>(buffer); | 11263 return FUNCTION_CAST<ModuloFunction>(buffer); |
11237 } | 11264 } |
11238 | 11265 |
11239 #endif | 11266 #endif |
11240 | 11267 |
11241 | 11268 |
11242 #undef __ | 11269 #undef __ |
11243 | 11270 |
11244 } } // namespace v8::internal | 11271 } } // namespace v8::internal |
OLD | NEW |