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 4782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4793 __ tst(value, Operand(kSmiTagMask)); | 4793 __ tst(value, Operand(kSmiTagMask)); |
4794 false_target()->Branch(eq); | 4794 false_target()->Branch(eq); |
4795 // Check that this is an object. | 4795 // Check that this is an object. |
4796 __ ldr(value, FieldMemOperand(value, HeapObject::kMapOffset)); | 4796 __ ldr(value, FieldMemOperand(value, HeapObject::kMapOffset)); |
4797 __ ldrb(value, FieldMemOperand(value, Map::kInstanceTypeOffset)); | 4797 __ ldrb(value, FieldMemOperand(value, Map::kInstanceTypeOffset)); |
4798 __ cmp(value, Operand(FIRST_JS_OBJECT_TYPE)); | 4798 __ cmp(value, Operand(FIRST_JS_OBJECT_TYPE)); |
4799 cc_reg_ = ge; | 4799 cc_reg_ = ge; |
4800 } | 4800 } |
4801 | 4801 |
4802 | 4802 |
| 4803 // Deferred code to check whether the String JavaScript object is safe for using |
| 4804 // default value of. This code is called after the bit caching this information |
| 4805 // in the map has been checked with the map for the object in the map_result_ |
| 4806 // register. On return the register map_result_ contains 1 for true and 0 for |
| 4807 // false. |
| 4808 class DeferredIsStringWrapperSafeForDefaultValueOf : public DeferredCode { |
| 4809 public: |
| 4810 DeferredIsStringWrapperSafeForDefaultValueOf(Register object, |
| 4811 Register map_result, |
| 4812 Register scratch1, |
| 4813 Register scratch2) |
| 4814 : object_(object), |
| 4815 map_result_(map_result), |
| 4816 scratch1_(scratch1), |
| 4817 scratch2_(scratch2) { } |
| 4818 |
| 4819 virtual void Generate() { |
| 4820 Label false_result; |
| 4821 |
| 4822 // Check that map is loaded as expected. |
| 4823 if (FLAG_debug_code) { |
| 4824 __ ldr(ip, FieldMemOperand(object_, HeapObject::kMapOffset)); |
| 4825 __ cmp(map_result_, ip); |
| 4826 __ Assert(eq, "Map not in expected register"); |
| 4827 } |
| 4828 |
| 4829 // Check for fast case object. Generate false result for slow case object. |
| 4830 __ ldr(scratch1_, FieldMemOperand(object_, JSObject::kPropertiesOffset)); |
| 4831 __ ldr(scratch1_, FieldMemOperand(scratch1_, HeapObject::kMapOffset)); |
| 4832 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); |
| 4833 __ cmp(scratch1_, ip); |
| 4834 __ b(eq, &false_result); |
| 4835 |
| 4836 // Look for valueOf symbol in the descriptor array, and indicate false if |
| 4837 // found. The type is not checked, so if it is a transition it is a false |
| 4838 // negative. |
| 4839 __ ldr(map_result_, |
| 4840 FieldMemOperand(map_result_, Map::kInstanceDescriptorsOffset)); |
| 4841 __ ldr(scratch2_, FieldMemOperand(map_result_, FixedArray::kLengthOffset)); |
| 4842 // map_result_: descriptor array |
| 4843 // scratch2_: length of descriptor array |
| 4844 // Calculate the end of the descriptor array. |
| 4845 STATIC_ASSERT(kSmiTag == 0); |
| 4846 STATIC_ASSERT(kSmiTagSize == 1); |
| 4847 STATIC_ASSERT(kPointerSize == 4); |
| 4848 __ add(scratch1_, |
| 4849 map_result_, |
| 4850 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 4851 __ add(scratch1_, |
| 4852 scratch1_, |
| 4853 Operand(scratch2_, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 4854 |
| 4855 // Calculate location of the first key name. |
| 4856 __ add(map_result_, |
| 4857 map_result_, |
| 4858 Operand(FixedArray::kHeaderSize + |
| 4859 DescriptorArray::kFirstIndex * kPointerSize)); |
| 4860 // Loop through all the keys in the descriptor array. If one of these is the |
| 4861 // symbol valueOf the result is false. |
| 4862 Label entry, loop; |
| 4863 __ jmp(&entry); |
| 4864 __ bind(&loop); |
| 4865 __ ldr(scratch2_, FieldMemOperand(map_result_, 0)); |
| 4866 __ cmp(scratch2_, Operand(Factory::value_of_symbol())); |
| 4867 __ b(eq, &false_result); |
| 4868 __ add(map_result_, map_result_, Operand(kPointerSize)); |
| 4869 __ bind(&entry); |
| 4870 __ cmp(map_result_, Operand(scratch1_)); |
| 4871 __ b(ne, &loop); |
| 4872 |
| 4873 // Reload map as register map_result_ was used as temporary above. |
| 4874 __ ldr(map_result_, FieldMemOperand(object_, HeapObject::kMapOffset)); |
| 4875 |
| 4876 // If a valueOf property is not found on the object check that it's |
| 4877 // prototype is the un-modified String prototype. If not result is false. |
| 4878 __ ldr(scratch1_, FieldMemOperand(map_result_, Map::kPrototypeOffset)); |
| 4879 __ tst(scratch1_, Operand(kSmiTagMask)); |
| 4880 __ b(eq, &false_result); |
| 4881 __ ldr(scratch1_, FieldMemOperand(scratch1_, HeapObject::kMapOffset)); |
| 4882 __ ldr(scratch2_, |
| 4883 CodeGenerator::ContextOperand(cp, Context::GLOBAL_INDEX)); |
| 4884 __ ldr(scratch2_, |
| 4885 FieldMemOperand(scratch2_, GlobalObject::kGlobalContextOffset)); |
| 4886 __ ldr(scratch2_, |
| 4887 CodeGenerator::ContextOperand( |
| 4888 scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
| 4889 __ cmp(scratch1_, scratch2_); |
| 4890 __ b(ne, &false_result); |
| 4891 |
| 4892 // Set the bit in the map to indicate that it has been checked safe for |
| 4893 // default valueOf and set true result. |
| 4894 __ ldr(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset)); |
| 4895 __ orr(scratch1_, |
| 4896 scratch1_, |
| 4897 Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 4898 __ str(scratch1_, FieldMemOperand(map_result_, Map::kBitField2Offset)); |
| 4899 __ mov(map_result_, Operand(1)); |
| 4900 __ jmp(exit_label()); |
| 4901 __ bind(&false_result); |
| 4902 // Set false result. |
| 4903 __ mov(map_result_, Operand(0)); |
| 4904 } |
| 4905 |
| 4906 private: |
| 4907 Register object_; |
| 4908 Register map_result_; |
| 4909 Register scratch1_; |
| 4910 Register scratch2_; |
| 4911 }; |
| 4912 |
| 4913 |
| 4914 void CodeGenerator::GenerateIsStringWrapperSafeForDefaultValueOf( |
| 4915 ZoneList<Expression*>* args) { |
| 4916 ASSERT(args->length() == 1); |
| 4917 Load(args->at(0)); |
| 4918 Register obj = frame_->PopToRegister(); // Pop the string wrapper. |
| 4919 if (FLAG_debug_code) { |
| 4920 __ AbortIfSmi(obj); |
| 4921 } |
| 4922 |
| 4923 // Check whether this map has already been checked to be safe for default |
| 4924 // valueOf. |
| 4925 Register map_result = VirtualFrame::scratch0(); |
| 4926 __ ldr(map_result, FieldMemOperand(obj, HeapObject::kMapOffset)); |
| 4927 __ ldrb(ip, FieldMemOperand(map_result, Map::kBitField2Offset)); |
| 4928 __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
| 4929 true_target()->Branch(ne); |
| 4930 |
| 4931 // We need an additional two scratch registers for the deferred code. |
| 4932 Register scratch1 = VirtualFrame::scratch1(); |
| 4933 // Use r6 without notifying the virtual frame. |
| 4934 Register scratch2 = r6; |
| 4935 |
| 4936 DeferredIsStringWrapperSafeForDefaultValueOf* deferred = |
| 4937 new DeferredIsStringWrapperSafeForDefaultValueOf( |
| 4938 obj, map_result, scratch1, scratch2); |
| 4939 deferred->Branch(eq); |
| 4940 deferred->BindExit(); |
| 4941 __ tst(map_result, Operand(map_result)); |
| 4942 cc_reg_ = ne; |
| 4943 } |
| 4944 |
| 4945 |
4803 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { | 4946 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { |
4804 // This generates a fast version of: | 4947 // This generates a fast version of: |
4805 // (%_ClassOf(arg) === 'Function') | 4948 // (%_ClassOf(arg) === 'Function') |
4806 ASSERT(args->length() == 1); | 4949 ASSERT(args->length() == 1); |
4807 Load(args->at(0)); | 4950 Load(args->at(0)); |
4808 Register possible_function = frame_->PopToRegister(); | 4951 Register possible_function = frame_->PopToRegister(); |
4809 __ tst(possible_function, Operand(kSmiTagMask)); | 4952 __ tst(possible_function, Operand(kSmiTagMask)); |
4810 false_target()->Branch(eq); | 4953 false_target()->Branch(eq); |
4811 Register map_reg = VirtualFrame::scratch0(); | 4954 Register map_reg = VirtualFrame::scratch0(); |
4812 Register scratch = VirtualFrame::scratch1(); | 4955 Register scratch = VirtualFrame::scratch1(); |
(...skipping 6628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11441 __ bind(&string_add_runtime); | 11584 __ bind(&string_add_runtime); |
11442 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 11585 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
11443 } | 11586 } |
11444 | 11587 |
11445 | 11588 |
11446 #undef __ | 11589 #undef __ |
11447 | 11590 |
11448 } } // namespace v8::internal | 11591 } } // namespace v8::internal |
11449 | 11592 |
11450 #endif // V8_TARGET_ARCH_ARM | 11593 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |