Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(300)

Side by Side Diff: src/arm/codegen-arm.cc

Issue 3117006: Handle overwriting valueOf on String objects correctly when adding... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/full-codegen-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/full-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698