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

Side by Side Diff: src/ia32/codegen-ia32.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/ia32/codegen-ia32.h ('k') | src/ia32/full-codegen-ia32.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 6744 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/full-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698