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

Side by Side Diff: src/x64/codegen-x64.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/x64/codegen-x64.h ('k') | src/x64/full-codegen-x64.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 6023 matching lines...) Expand 10 before | Expand all | Expand 10 after
6034 ASSERT(value.is_valid()); 6034 ASSERT(value.is_valid());
6035 Condition is_smi = masm_->CheckSmi(value.reg()); 6035 Condition is_smi = masm_->CheckSmi(value.reg());
6036 destination()->false_target()->Branch(is_smi); 6036 destination()->false_target()->Branch(is_smi);
6037 // Check that this is an object. 6037 // Check that this is an object.
6038 __ CmpObjectType(value.reg(), FIRST_JS_OBJECT_TYPE, kScratchRegister); 6038 __ CmpObjectType(value.reg(), FIRST_JS_OBJECT_TYPE, kScratchRegister);
6039 value.Unuse(); 6039 value.Unuse();
6040 destination()->Split(above_equal); 6040 destination()->Split(above_equal);
6041 } 6041 }
6042 6042
6043 6043
6044 // Deferred code to check whether the String JavaScript object is safe for using
6045 // default value of. This code is called after the bit caching this information
6046 // in the map has been checked with the map for the object in the map_result_
6047 // register. On return the register map_result_ contains 1 for true and 0 for
6048 // false.
6049 class DeferredIsStringWrapperSafeForDefaultValueOf : public DeferredCode {
6050 public:
6051 DeferredIsStringWrapperSafeForDefaultValueOf(Register object,
6052 Register map_result,
6053 Register scratch1,
6054 Register scratch2)
6055 : object_(object),
6056 map_result_(map_result),
6057 scratch1_(scratch1),
6058 scratch2_(scratch2) { }
6059
6060 virtual void Generate() {
6061 Label false_result;
6062
6063 // Check that map is loaded as expected.
6064 if (FLAG_debug_code) {
6065 __ cmpq(map_result_, FieldOperand(object_, HeapObject::kMapOffset));
6066 __ Assert(equal, "Map not in expected register");
6067 }
6068
6069 // Check for fast case object. Generate false result for slow case object.
6070 __ movq(scratch1_, FieldOperand(object_, JSObject::kPropertiesOffset));
6071 __ movq(scratch1_, FieldOperand(scratch1_, HeapObject::kMapOffset));
6072 __ CompareRoot(scratch1_, Heap::kHashTableMapRootIndex);
6073 __ j(equal, &false_result);
6074
6075 // Look for valueOf symbol in the descriptor array, and indicate false if
6076 // found. The type is not checked, so if it is a transition it is a false
6077 // negative.
6078 __ movq(map_result_,
6079 FieldOperand(map_result_, Map::kInstanceDescriptorsOffset));
6080 __ movq(scratch1_, FieldOperand(map_result_, FixedArray::kLengthOffset));
6081 // map_result_: descriptor array
6082 // scratch1_: length of descriptor array
6083 // Calculate the end of the descriptor array.
6084 SmiIndex index = masm_->SmiToIndex(scratch2_, scratch1_, kPointerSizeLog2);
6085 __ lea(scratch1_,
6086 Operand(
6087 map_result_, index.reg, index.scale, FixedArray::kHeaderSize));
6088 // Calculate location of the first key name.
6089 __ addq(map_result_,
6090 Immediate(FixedArray::kHeaderSize +
6091 DescriptorArray::kFirstIndex * kPointerSize));
6092 // Loop through all the keys in the descriptor array. If one of these is the
6093 // symbol valueOf the result is false.
6094 Label entry, loop;
6095 __ jmp(&entry);
6096 __ bind(&loop);
6097 __ movq(scratch2_, FieldOperand(map_result_, 0));
6098 __ Cmp(scratch2_, Factory::value_of_symbol());
6099 __ j(equal, &false_result);
6100 __ addq(map_result_, Immediate(kPointerSize));
6101 __ bind(&entry);
6102 __ cmpq(map_result_, scratch1_);
6103 __ j(not_equal, &loop);
6104
6105 // Reload map as register map_result_ was used as temporary above.
6106 __ movq(map_result_, FieldOperand(object_, HeapObject::kMapOffset));
6107
6108 // If a valueOf property is not found on the object check that it's
6109 // prototype is the un-modified String prototype. If not result is false.
6110 __ movq(scratch1_, FieldOperand(map_result_, Map::kPrototypeOffset));
6111 __ testq(scratch1_, Immediate(kSmiTagMask));
6112 __ j(zero, &false_result);
6113 __ movq(scratch1_, FieldOperand(scratch1_, HeapObject::kMapOffset));
6114 __ movq(scratch2_,
6115 Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
6116 __ movq(scratch2_,
6117 FieldOperand(scratch2_, GlobalObject::kGlobalContextOffset));
6118 __ cmpq(scratch1_,
6119 CodeGenerator::ContextOperand(
6120 scratch2_, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
6121 __ j(not_equal, &false_result);
6122 // Set the bit in the map to indicate that it has been checked safe for
6123 // default valueOf and set true result.
6124 __ or_(FieldOperand(map_result_, Map::kBitField2Offset),
6125 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
6126 __ Set(map_result_, 1);
6127 __ jmp(exit_label());
6128 __ bind(&false_result);
6129 // Set false result.
6130 __ Set(map_result_, 0);
6131 }
6132
6133 private:
6134 Register object_;
6135 Register map_result_;
6136 Register scratch1_;
6137 Register scratch2_;
6138 };
6139
6140
6141 void CodeGenerator::GenerateIsStringWrapperSafeForDefaultValueOf(
6142 ZoneList<Expression*>* args) {
6143 ASSERT(args->length() == 1);
6144 Load(args->at(0));
6145 Result obj = frame_->Pop(); // Pop the string wrapper.
6146 obj.ToRegister();
6147 ASSERT(obj.is_valid());
6148 if (FLAG_debug_code) {
6149 __ AbortIfSmi(obj.reg());
6150 }
6151
6152 // Check whether this map has already been checked to be safe for default
6153 // valueOf.
6154 Result map_result = allocator()->Allocate();
6155 ASSERT(map_result.is_valid());
6156 __ movq(map_result.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset));
6157 __ testb(FieldOperand(map_result.reg(), Map::kBitField2Offset),
6158 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
6159 destination()->true_target()->Branch(not_zero);
6160
6161 // We need an additional two scratch registers for the deferred code.
6162 Result temp1 = allocator()->Allocate();
6163 ASSERT(temp1.is_valid());
6164 Result temp2 = allocator()->Allocate();
6165 ASSERT(temp2.is_valid());
6166
6167 DeferredIsStringWrapperSafeForDefaultValueOf* deferred =
6168 new DeferredIsStringWrapperSafeForDefaultValueOf(
6169 obj.reg(), map_result.reg(), temp1.reg(), temp2.reg());
6170 deferred->Branch(zero);
6171 deferred->BindExit();
6172 __ testq(map_result.reg(), map_result.reg());
6173 obj.Unuse();
6174 map_result.Unuse();
6175 temp1.Unuse();
6176 temp2.Unuse();
6177 destination()->Split(not_equal);
6178 }
6179
6180
6044 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { 6181 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) {
6045 // This generates a fast version of: 6182 // This generates a fast version of:
6046 // (%_ClassOf(arg) === 'Function') 6183 // (%_ClassOf(arg) === 'Function')
6047 ASSERT(args->length() == 1); 6184 ASSERT(args->length() == 1);
6048 Load(args->at(0)); 6185 Load(args->at(0));
6049 Result obj = frame_->Pop(); 6186 Result obj = frame_->Pop();
6050 obj.ToRegister(); 6187 obj.ToRegister();
6051 Condition is_smi = masm_->CheckSmi(obj.reg()); 6188 Condition is_smi = masm_->CheckSmi(obj.reg());
6052 destination()->false_target()->Branch(is_smi); 6189 destination()->false_target()->Branch(is_smi);
6053 __ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, kScratchRegister); 6190 __ CmpObjectType(obj.reg(), JS_FUNCTION_TYPE, kScratchRegister);
(...skipping 6562 matching lines...) Expand 10 before | Expand all | Expand 10 after
12616 #undef __ 12753 #undef __
12617 12754
12618 void RecordWriteStub::Generate(MacroAssembler* masm) { 12755 void RecordWriteStub::Generate(MacroAssembler* masm) {
12619 masm->RecordWriteHelper(object_, addr_, scratch_); 12756 masm->RecordWriteHelper(object_, addr_, scratch_);
12620 masm->ret(0); 12757 masm->ret(0);
12621 } 12758 }
12622 12759
12623 } } // namespace v8::internal 12760 } } // namespace v8::internal
12624 12761
12625 #endif // V8_TARGET_ARCH_X64 12762 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698