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 6744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6755 // ControlDestination, so we copy its implementation here. | 6755 // ControlDestination, so we copy its implementation here. |
6756 __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset)); | 6756 __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset)); |
6757 __ sub(Operand(map.reg()), Immediate(FIRST_JS_OBJECT_TYPE)); | 6757 __ sub(Operand(map.reg()), Immediate(FIRST_JS_OBJECT_TYPE)); |
6758 __ cmp(map.reg(), LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE); | 6758 __ cmp(map.reg(), LAST_JS_OBJECT_TYPE - FIRST_JS_OBJECT_TYPE); |
6759 obj.Unuse(); | 6759 obj.Unuse(); |
6760 map.Unuse(); | 6760 map.Unuse(); |
6761 destination()->Split(below_equal); | 6761 destination()->Split(below_equal); |
6762 } | 6762 } |
6763 | 6763 |
6764 | 6764 |
6765 void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) { | 6765 void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) { |
6766 // This generates a fast version of: | 6766 // This generates a fast version of: |
6767 // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp' || | 6767 // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp' || |
6768 // typeof(arg) == function). | 6768 // typeof(arg) == function). |
6769 // It includes undetectable objects (as opposed to IsObject). | 6769 // It includes undetectable objects (as opposed to IsObject). |
6770 ASSERT(args->length() == 1); | 6770 ASSERT(args->length() == 1); |
6771 Load(args->at(0)); | 6771 Load(args->at(0)); |
6772 Result value = frame_->Pop(); | 6772 Result value = frame_->Pop(); |
6773 value.ToRegister(); | 6773 value.ToRegister(); |
6774 ASSERT(value.is_valid()); | 6774 ASSERT(value.is_valid()); |
6775 __ test(value.reg(), Immediate(kSmiTagMask)); | 6775 __ test(value.reg(), Immediate(kSmiTagMask)); |
6776 destination()->false_target()->Branch(equal); | 6776 destination()->false_target()->Branch(equal); |
6777 | 6777 |
6778 // Check that this is an object. | 6778 // Check that this is an object. |
6779 frame_->Spill(value.reg()); | 6779 frame_->Spill(value.reg()); |
6780 __ CmpObjectType(value.reg(), FIRST_JS_OBJECT_TYPE, value.reg()); | 6780 __ CmpObjectType(value.reg(), FIRST_JS_OBJECT_TYPE, value.reg()); |
6781 value.Unuse(); | 6781 value.Unuse(); |
6782 destination()->Split(above_equal); | 6782 destination()->Split(above_equal); |
6783 } | 6783 } |
6784 | 6784 |
6785 | 6785 |
| 6786 // Deferred code to check whether the String JavaScript object is safe for using |
| 6787 // default value of. This code is called after the bit caching this information |
| 6788 // in the map has been checked with the map for the object in the map_result_ |
| 6789 // register. On return the register map_result_ contains 1 for true and 0 for |
| 6790 // false. |
| 6791 class DeferredIsStringWrapperSafeForDefaultValueOf : public DeferredCode { |
| 6792 public: |
| 6793 DeferredIsStringWrapperSafeForDefaultValueOf(Register object, |
| 6794 Register map_result, |
| 6795 Register scratch1, |
| 6796 Register scratch2) |
| 6797 : object_(object), |
| 6798 map_result_(map_result), |
| 6799 scratch1_(scratch1), |
| 6800 scratch2_(scratch2) { } |
| 6801 |
| 6802 virtual void Generate() { |
| 6803 Label false_result; |
| 6804 |
| 6805 // Check that map is loaded as expected. |
| 6806 if (FLAG_debug_code) { |
| 6807 __ cmp(map_result_, FieldOperand(object_, HeapObject::kMapOffset)); |
| 6808 __ Assert(equal, "Map not in expected register"); |
| 6809 } |
| 6810 |
| 6811 // Check for fast case object. Generate false result for slow case object. |
| 6812 __ mov(scratch1_, FieldOperand(object_, JSObject::kPropertiesOffset)); |
| 6813 __ mov(scratch1_, FieldOperand(scratch1_, HeapObject::kMapOffset)); |
| 6814 __ cmp(scratch1_, Factory::hash_table_map()); |
| 6815 __ j(equal, &false_result); |
| 6816 |
| 6817 // Look for valueOf symbol in the descriptor array, and indicate false if |
| 6818 // found. The type is not checked, so if it is a transition it is a false |
| 6819 // negative. |
| 6820 __ mov(map_result_, |
| 6821 FieldOperand(map_result_, Map::kInstanceDescriptorsOffset)); |
| 6822 __ mov(scratch1_, FieldOperand(map_result_, FixedArray::kLengthOffset)); |
| 6823 // map_result_: descriptor array |
| 6824 // scratch1_: length of descriptor array |
| 6825 // Calculate the end of the descriptor array. |
| 6826 STATIC_ASSERT(kSmiTag == 0); |
| 6827 STATIC_ASSERT(kSmiTagSize == 1); |
| 6828 STATIC_ASSERT(kPointerSize == 4); |
| 6829 __ lea(scratch1_, |
| 6830 Operand(map_result_, scratch1_, times_2, FixedArray::kHeaderSize)); |
| 6831 // Calculate location of the first key name. |
| 6832 __ add(Operand(map_result_), |
| 6833 Immediate(FixedArray::kHeaderSize + |
| 6834 DescriptorArray::kFirstIndex * kPointerSize)); |
| 6835 // Loop through all the keys in the descriptor array. If one of these is the |
| 6836 // symbol valueOf the result is false. |
| 6837 Label entry, loop; |
| 6838 __ jmp(&entry); |
| 6839 __ bind(&loop); |
| 6840 __ mov(scratch2_, FieldOperand(map_result_, 0)); |
| 6841 __ cmp(scratch2_, Factory::value_of_symbol()); |
| 6842 __ j(equal, &false_result); |
| 6843 __ add(Operand(map_result_), Immediate(kPointerSize)); |
| 6844 __ bind(&entry); |
| 6845 __ cmp(map_result_, Operand(scratch1_)); |
| 6846 __ j(not_equal, &loop); |
| 6847 |
| 6848 // Reload map as register map_result_ was used as temporary above. |
| 6849 __ mov(map_result_, FieldOperand(object_, HeapObject::kMapOffset)); |
| 6850 |
| 6851 // If a valueOf property is not found on the object check that it's |
| 6852 // prototype is the un-modified String prototype. If not result is false. |
| 6853 __ mov(scratch1_, FieldOperand(map_result_, Map::kPrototypeOffset)); |
| 6854 __ test(scratch1_, Immediate(kSmiTagMask)); |
| 6855 __ j(zero, &false_result); |
| 6856 __ mov(scratch1_, FieldOperand(scratch1_, HeapObject::kMapOffset)); |
| 6857 __ mov(scratch2_, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 6858 __ mov(scratch2_, |
| 6859 FieldOperand(scratch2_, GlobalObject::kGlobalContextOffset)); |
| 6860 __ cmp(scratch1_, |
| 6861 CodeGenerator::ContextOperand( |
| 6862 scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
| 6863 __ j(not_equal, &false_result); |
| 6864 // Set the bit in the map to indicate that it has been checked safe for |
| 6865 // default valueOf and set true result. |
| 6866 __ or_(FieldOperand(map_result_, Map::kBitField2Offset), |
| 6867 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 6868 __ Set(map_result_, Immediate(1)); |
| 6869 __ jmp(exit_label()); |
| 6870 __ bind(&false_result); |
| 6871 // Set false result. |
| 6872 __ Set(map_result_, Immediate(0)); |
| 6873 } |
| 6874 |
| 6875 private: |
| 6876 Register object_; |
| 6877 Register map_result_; |
| 6878 Register scratch1_; |
| 6879 Register scratch2_; |
| 6880 }; |
| 6881 |
| 6882 |
| 6883 void CodeGenerator::GenerateIsStringWrapperSafeForDefaultValueOf( |
| 6884 ZoneList<Expression*>* args) { |
| 6885 ASSERT(args->length() == 1); |
| 6886 Load(args->at(0)); |
| 6887 Result obj = frame_->Pop(); // Pop the string wrapper. |
| 6888 obj.ToRegister(); |
| 6889 ASSERT(obj.is_valid()); |
| 6890 if (FLAG_debug_code) { |
| 6891 __ AbortIfSmi(obj.reg()); |
| 6892 } |
| 6893 |
| 6894 // Check whether this map has already been checked to be safe for default |
| 6895 // valueOf. |
| 6896 Result map_result = allocator()->Allocate(); |
| 6897 ASSERT(map_result.is_valid()); |
| 6898 __ mov(map_result.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset)); |
| 6899 __ test_b(FieldOperand(map_result.reg(), Map::kBitField2Offset), |
| 6900 1 << Map::kStringWrapperSafeForDefaultValueOf); |
| 6901 destination()->true_target()->Branch(not_zero); |
| 6902 |
| 6903 // We need an additional two scratch registers for the deferred code. |
| 6904 Result temp1 = allocator()->Allocate(); |
| 6905 ASSERT(temp1.is_valid()); |
| 6906 Result temp2 = allocator()->Allocate(); |
| 6907 ASSERT(temp2.is_valid()); |
| 6908 |
| 6909 DeferredIsStringWrapperSafeForDefaultValueOf* deferred = |
| 6910 new DeferredIsStringWrapperSafeForDefaultValueOf( |
| 6911 obj.reg(), map_result.reg(), temp1.reg(), temp2.reg()); |
| 6912 deferred->Branch(zero); |
| 6913 deferred->BindExit(); |
| 6914 __ test(map_result.reg(), Operand(map_result.reg())); |
| 6915 obj.Unuse(); |
| 6916 map_result.Unuse(); |
| 6917 temp1.Unuse(); |
| 6918 temp2.Unuse(); |
| 6919 destination()->Split(not_equal); |
| 6920 } |
| 6921 |
| 6922 |
6786 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { | 6923 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { |
6787 // This generates a fast version of: | 6924 // This generates a fast version of: |
6788 // (%_ClassOf(arg) === 'Function') | 6925 // (%_ClassOf(arg) === 'Function') |
6789 ASSERT(args->length() == 1); | 6926 ASSERT(args->length() == 1); |
6790 Load(args->at(0)); | 6927 Load(args->at(0)); |
6791 Result obj = frame_->Pop(); | 6928 Result obj = frame_->Pop(); |
6792 obj.ToRegister(); | 6929 obj.ToRegister(); |
6793 __ test(obj.reg(), Immediate(kSmiTagMask)); | 6930 __ test(obj.reg(), Immediate(kSmiTagMask)); |
6794 destination()->false_target()->Branch(zero); | 6931 destination()->false_target()->Branch(zero); |
6795 Result temp = allocator()->Allocate(); | 6932 Result temp = allocator()->Allocate(); |
(...skipping 7465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14261 masm.GetCode(&desc); | 14398 masm.GetCode(&desc); |
14262 // Call the function from C++. | 14399 // Call the function from C++. |
14263 return FUNCTION_CAST<MemCopyFunction>(buffer); | 14400 return FUNCTION_CAST<MemCopyFunction>(buffer); |
14264 } | 14401 } |
14265 | 14402 |
14266 #undef __ | 14403 #undef __ |
14267 | 14404 |
14268 } } // namespace v8::internal | 14405 } } // namespace v8::internal |
14269 | 14406 |
14270 #endif // V8_TARGET_ARCH_IA32 | 14407 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |