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

Side by Side Diff: src/objects.cc

Issue 1705713002: [runtime] Replace hidden_string with a 0-hash-code private symbol (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 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
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/objects.h" 5 #include "src/objects.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 #include <iomanip> 8 #include <iomanip>
9 #include <sstream> 9 #include <sstream>
10 10
(...skipping 4403 matching lines...) Expand 10 before | Expand all | Expand 10 after
4414 // properties. 4414 // properties.
4415 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); 4415 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
4416 4416
4417 // Store on the holder which may be hidden behind the receiver. 4417 // Store on the holder which may be hidden behind the receiver.
4418 DCHECK(it->HolderIsReceiverOrHiddenPrototype()); 4418 DCHECK(it->HolderIsReceiverOrHiddenPrototype());
4419 4419
4420 // Old value for the observation change record. 4420 // Old value for the observation change record.
4421 // Fetch before transforming the object since the encoding may become 4421 // Fetch before transforming the object since the encoding may become
4422 // incompatible with what's cached in |it|. 4422 // incompatible with what's cached in |it|.
4423 bool is_observed = receiver->map()->is_observed() && 4423 bool is_observed = receiver->map()->is_observed() &&
4424 (it->IsElement() || 4424 (it->IsElement() || !it->name()->IsPrivate());
4425 !it->isolate()->IsInternallyUsedPropertyName(it->name()));
4426 MaybeHandle<Object> maybe_old; 4425 MaybeHandle<Object> maybe_old;
4427 if (is_observed) maybe_old = it->GetDataValue(); 4426 if (is_observed) maybe_old = it->GetDataValue();
4428 4427
4429 Handle<Object> to_assign = value; 4428 Handle<Object> to_assign = value;
4430 // Convert the incoming value to a number for storing into typed arrays. 4429 // Convert the incoming value to a number for storing into typed arrays.
4431 if (it->IsElement() && receiver->HasFixedTypedArrayElements()) { 4430 if (it->IsElement() && receiver->HasFixedTypedArrayElements()) {
4432 if (!value->IsNumber() && !value->IsUndefined()) { 4431 if (!value->IsNumber() && !value->IsUndefined()) {
4433 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 4432 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
4434 it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>()); 4433 it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>());
4435 // We have to recheck the length. However, it can only change if the 4434 // We have to recheck the length. However, it can only change if the
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
4570 // TODO(verwaest): Probably should ensure this is done beforehand. 4569 // TODO(verwaest): Probably should ensure this is done beforehand.
4571 it->InternalizeName(); 4570 it->InternalizeName();
4572 // TODO(dcarney): just populate TransitionPropertyCell here? 4571 // TODO(dcarney): just populate TransitionPropertyCell here?
4573 JSObject::AddSlowProperty(receiver, it->name(), value, attributes); 4572 JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
4574 } else { 4573 } else {
4575 // Write the property value. 4574 // Write the property value.
4576 it->WriteDataValue(value); 4575 it->WriteDataValue(value);
4577 } 4576 }
4578 4577
4579 // Send the change record if there are observers. 4578 // Send the change record if there are observers.
4580 if (receiver->map()->is_observed() && 4579 if (receiver->map()->is_observed() && !it->name()->IsPrivate()) {
4581 !isolate->IsInternallyUsedPropertyName(it->name())) {
4582 RETURN_ON_EXCEPTION_VALUE(isolate, JSObject::EnqueueChangeRecord( 4580 RETURN_ON_EXCEPTION_VALUE(isolate, JSObject::EnqueueChangeRecord(
4583 receiver, "add", it->name(), 4581 receiver, "add", it->name(),
4584 it->factory()->the_hole_value()), 4582 it->factory()->the_hole_value()),
4585 Nothing<bool>()); 4583 Nothing<bool>());
4586 } 4584 }
4587 #if VERIFY_HEAP 4585 #if VERIFY_HEAP
4588 if (FLAG_verify_heap) { 4586 if (FLAG_verify_heap) {
4589 receiver->JSObjectVerify(); 4587 receiver->JSObjectVerify();
4590 } 4588 }
4591 #endif 4589 #endif
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
5272 PropertyAttributes attributes) { 5270 PropertyAttributes attributes) {
5273 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); 5271 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
5274 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state()); 5272 CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
5275 #ifdef DEBUG 5273 #ifdef DEBUG
5276 uint32_t index; 5274 uint32_t index;
5277 DCHECK(!object->IsJSProxy()); 5275 DCHECK(!object->IsJSProxy());
5278 DCHECK(!name->AsArrayIndex(&index)); 5276 DCHECK(!name->AsArrayIndex(&index));
5279 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); 5277 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
5280 DCHECK(maybe.IsJust()); 5278 DCHECK(maybe.IsJust());
5281 DCHECK(!it.IsFound()); 5279 DCHECK(!it.IsFound());
5282 DCHECK(object->map()->is_extensible() || 5280 DCHECK(object->map()->is_extensible() || name->IsPrivate());
5283 it.isolate()->IsInternallyUsedPropertyName(name));
5284 #endif 5281 #endif
5285 CHECK(AddDataProperty(&it, value, attributes, THROW_ON_ERROR, 5282 CHECK(AddDataProperty(&it, value, attributes, THROW_ON_ERROR,
5286 CERTAINLY_NOT_STORE_FROM_KEYED) 5283 CERTAINLY_NOT_STORE_FROM_KEYED)
5287 .IsJust()); 5284 .IsJust());
5288 } 5285 }
5289 5286
5290 5287
5291 // Reconfigures a property to a data property with attributes, even if it is not 5288 // Reconfigures a property to a data property with attributes, even if it is not
5292 // reconfigurable. 5289 // reconfigurable.
5293 // Requires a LookupIterator that does not look at the prototype chain beyond 5290 // Requires a LookupIterator that does not look at the prototype chain beyond
5294 // hidden prototypes. 5291 // hidden prototypes.
5295 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes( 5292 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
5296 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, 5293 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
5297 AccessorInfoHandling handling) { 5294 AccessorInfoHandling handling) {
5298 MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes( 5295 MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes(
5299 it, value, attributes, THROW_ON_ERROR, handling)); 5296 it, value, attributes, THROW_ON_ERROR, handling));
5300 return value; 5297 return value;
5301 } 5298 }
5302 5299
5303 5300
5304 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes( 5301 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
5305 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes, 5302 LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
5306 ShouldThrow should_throw, AccessorInfoHandling handling) { 5303 ShouldThrow should_throw, AccessorInfoHandling handling) {
5307 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); 5304 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
5308 bool is_observed = object->map()->is_observed() && 5305 bool is_observed = object->map()->is_observed() &&
5309 (it->IsElement() || 5306 (it->IsElement() || !it->name()->IsPrivate());
5310 !it->isolate()->IsInternallyUsedPropertyName(it->name()));
5311 5307
5312 for (; it->IsFound(); it->Next()) { 5308 for (; it->IsFound(); it->Next()) {
5313 switch (it->state()) { 5309 switch (it->state()) {
5314 case LookupIterator::JSPROXY: 5310 case LookupIterator::JSPROXY:
5315 case LookupIterator::NOT_FOUND: 5311 case LookupIterator::NOT_FOUND:
5316 case LookupIterator::TRANSITION: 5312 case LookupIterator::TRANSITION:
5317 UNREACHABLE(); 5313 UNREACHABLE();
5318 5314
5319 case LookupIterator::ACCESS_CHECK: 5315 case LookupIterator::ACCESS_CHECK:
5320 if (!it->HasAccess()) { 5316 if (!it->HasAccess()) {
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after
6027 6023
6028 if (inline_value->IsUndefined()) return; 6024 if (inline_value->IsUndefined()) return;
6029 6025
6030 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); 6026 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value));
6031 bool was_present = false; 6027 bool was_present = false;
6032 ObjectHashTable::Remove(hashtable, key, &was_present); 6028 ObjectHashTable::Remove(hashtable, key, &was_present);
6033 } 6029 }
6034 6030
6035 6031
6036 bool JSObject::HasHiddenProperties(Handle<JSObject> object) { 6032 bool JSObject::HasHiddenProperties(Handle<JSObject> object) {
6037 Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string(); 6033 Isolate* isolate = object->GetIsolate();
6038 LookupIterator it(object, hidden, LookupIterator::OWN_SKIP_INTERCEPTOR); 6034 Handle<Symbol> hidden = isolate->factory()->hidden_properties_symbol();
6035 LookupIterator it(object, hidden);
6039 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it); 6036 Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
6040 // Cannot get an exception since the hidden_string isn't accessible to JS. 6037 // Cannot get an exception since the hidden_properties_symbol isn't exposed to
6038 // JS.
6041 DCHECK(maybe.IsJust()); 6039 DCHECK(maybe.IsJust());
6042 return maybe.FromJust() != ABSENT; 6040 return maybe.FromJust() != ABSENT;
6043 } 6041 }
6044 6042
6045 6043
6046 Object* JSObject::GetHiddenPropertiesHashTable() { 6044 Object* JSObject::GetHiddenPropertiesHashTable() {
6047 DCHECK(!IsJSGlobalProxy()); 6045 DCHECK(!IsJSGlobalProxy());
6048 if (HasFastProperties()) { 6046 if (HasFastProperties()) {
6049 // If the object has fast properties, check whether the first slot 6047 // If the object has fast properties, check whether the first slot
6050 // in the descriptor array matches the hidden string. Since the 6048 // in the descriptor array matches the hidden string. Since the
6051 // hidden strings hash code is zero (and no other name has hash 6049 // hidden strings hash code is zero (and no other name has hash
6052 // code zero) it will always occupy the first entry if present. 6050 // code zero) it will always occupy the first entry if present.
6053 DescriptorArray* descriptors = this->map()->instance_descriptors(); 6051 DescriptorArray* descriptors = this->map()->instance_descriptors();
6054 if (descriptors->number_of_descriptors() > 0) { 6052 if (descriptors->number_of_descriptors() > 0) {
6055 int sorted_index = descriptors->GetSortedKeyIndex(0); 6053 int sorted_index = descriptors->GetSortedKeyIndex(0);
6056 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && 6054 if (descriptors->GetKey(sorted_index) ==
6055 GetHeap()->hidden_properties_symbol() &&
6057 sorted_index < map()->NumberOfOwnDescriptors()) { 6056 sorted_index < map()->NumberOfOwnDescriptors()) {
6058 DCHECK(descriptors->GetType(sorted_index) == DATA); 6057 DCHECK(descriptors->GetType(sorted_index) == DATA);
6059 DCHECK(descriptors->GetDetails(sorted_index).representation(). 6058 DCHECK(descriptors->GetDetails(sorted_index).representation().
6060 IsCompatibleForLoad(Representation::Tagged())); 6059 IsCompatibleForLoad(Representation::Tagged()));
6061 FieldIndex index = FieldIndex::ForDescriptor(this->map(), 6060 FieldIndex index = FieldIndex::ForDescriptor(this->map(),
6062 sorted_index); 6061 sorted_index);
6063 return this->RawFastPropertyAt(index); 6062 return this->RawFastPropertyAt(index);
6064 } else { 6063 } else {
6065 return GetHeap()->undefined_value(); 6064 return GetHeap()->undefined_value();
6066 } 6065 }
6067 } else { 6066 } else {
6068 return GetHeap()->undefined_value(); 6067 return GetHeap()->undefined_value();
6069 } 6068 }
6070 } else { 6069 } else {
6071 Isolate* isolate = GetIsolate(); 6070 Handle<Symbol> hidden = GetIsolate()->factory()->hidden_properties_symbol();
6072 LookupIterator it(handle(this), isolate->factory()->hidden_string(), 6071 LookupIterator it(handle(this), hidden);
6073 LookupIterator::OWN_SKIP_INTERCEPTOR);
6074 // Access check is always skipped for the hidden string anyways. 6072 // Access check is always skipped for the hidden string anyways.
6075 return *GetDataProperty(&it); 6073 return *GetDataProperty(&it);
6076 } 6074 }
6077 } 6075 }
6078 6076
6079 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable( 6077 Handle<ObjectHashTable> JSObject::GetOrCreateHiddenPropertiesHashtable(
6080 Handle<JSObject> object) { 6078 Handle<JSObject> object) {
6081 Isolate* isolate = object->GetIsolate(); 6079 Isolate* isolate = object->GetIsolate();
6082 6080
6083 static const int kInitialCapacity = 4; 6081 static const int kInitialCapacity = 4;
6084 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); 6082 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate);
6085 if (inline_value->IsHashTable()) { 6083 if (inline_value->IsHashTable()) {
6086 return Handle<ObjectHashTable>::cast(inline_value); 6084 return Handle<ObjectHashTable>::cast(inline_value);
6087 } 6085 }
6088 6086
6089 Handle<ObjectHashTable> hashtable = ObjectHashTable::New( 6087 Handle<ObjectHashTable> hashtable = ObjectHashTable::New(
6090 isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY); 6088 isolate, kInitialCapacity, USE_CUSTOM_MINIMUM_CAPACITY);
6091 6089
6092 DCHECK(inline_value->IsUndefined()); 6090 DCHECK(inline_value->IsUndefined());
6093 SetHiddenPropertiesHashTable(object, hashtable); 6091 SetHiddenPropertiesHashTable(object, hashtable);
6094 return hashtable; 6092 return hashtable;
6095 } 6093 }
6096 6094
6097 6095
6098 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, 6096 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object,
6099 Handle<Object> value) { 6097 Handle<Object> value) {
6100 DCHECK(!object->IsJSGlobalProxy()); 6098 DCHECK(!object->IsJSGlobalProxy());
6101 Isolate* isolate = object->GetIsolate(); 6099 Isolate* isolate = object->GetIsolate();
6102 Handle<Name> name = isolate->factory()->hidden_string(); 6100 Handle<Symbol> name = isolate->factory()->hidden_properties_symbol();
6103 SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert(); 6101 SetOwnPropertyIgnoreAttributes(object, name, value, DONT_ENUM).Assert();
6104 return object; 6102 return object;
6105 } 6103 }
6106 6104
6107 6105
6108 Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it, 6106 Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it,
6109 ShouldThrow should_throw) { 6107 ShouldThrow should_throw) {
6110 Isolate* isolate = it->isolate(); 6108 Isolate* isolate = it->isolate();
6111 // Make sure that the top context does not change when doing callbacks or 6109 // Make sure that the top context does not change when doing callbacks or
6112 // interceptor calls. 6110 // interceptor calls.
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
6192 if (it->GetReceiver()->IsJSProxy()) { 6190 if (it->GetReceiver()->IsJSProxy()) {
6193 if (it->state() != LookupIterator::NOT_FOUND) { 6191 if (it->state() != LookupIterator::NOT_FOUND) {
6194 DCHECK_EQ(LookupIterator::DATA, it->state()); 6192 DCHECK_EQ(LookupIterator::DATA, it->state());
6195 DCHECK(it->GetName()->IsPrivate()); 6193 DCHECK(it->GetName()->IsPrivate());
6196 it->Delete(); 6194 it->Delete();
6197 } 6195 }
6198 return Just(true); 6196 return Just(true);
6199 } 6197 }
6200 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver()); 6198 Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
6201 6199
6202 bool is_observed = 6200 bool is_observed = receiver->map()->is_observed() &&
6203 receiver->map()->is_observed() && 6201 (it->IsElement() || !it->name()->IsPrivate());
6204 (it->IsElement() || !isolate->IsInternallyUsedPropertyName(it->name()));
6205 6202
6206 Handle<Object> old_value = it->factory()->the_hole_value(); 6203 Handle<Object> old_value = it->factory()->the_hole_value();
6207 6204
6208 for (; it->IsFound(); it->Next()) { 6205 for (; it->IsFound(); it->Next()) {
6209 switch (it->state()) { 6206 switch (it->state()) {
6210 case LookupIterator::JSPROXY: 6207 case LookupIterator::JSPROXY:
6211 case LookupIterator::NOT_FOUND: 6208 case LookupIterator::NOT_FOUND:
6212 case LookupIterator::TRANSITION: 6209 case LookupIterator::TRANSITION:
6213 UNREACHABLE(); 6210 UNREACHABLE();
6214 case LookupIterator::ACCESS_CHECK: 6211 case LookupIterator::ACCESS_CHECK:
(...skipping 2837 matching lines...) Expand 10 before | Expand all | Expand 10 after
9052 } 9049 }
9053 9050
9054 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver()); 9051 Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
9055 // Ignore accessors on typed arrays. 9052 // Ignore accessors on typed arrays.
9056 if (it->IsElement() && object->HasFixedTypedArrayElements()) { 9053 if (it->IsElement() && object->HasFixedTypedArrayElements()) {
9057 return it->factory()->undefined_value(); 9054 return it->factory()->undefined_value();
9058 } 9055 }
9059 9056
9060 Handle<Object> old_value = isolate->factory()->the_hole_value(); 9057 Handle<Object> old_value = isolate->factory()->the_hole_value();
9061 bool is_observed = object->map()->is_observed() && 9058 bool is_observed = object->map()->is_observed() &&
9062 !isolate->IsInternallyUsedPropertyName(it->GetName()); 9059 (it->IsElement() || !it->name()->IsPrivate());
9063 bool preexists = false; 9060 bool preexists = false;
9064 if (is_observed) { 9061 if (is_observed) {
9065 CHECK(GetPropertyAttributes(it).IsJust()); 9062 CHECK(GetPropertyAttributes(it).IsJust());
9066 preexists = it->IsFound(); 9063 preexists = it->IsFound();
9067 if (preexists && (it->state() == LookupIterator::DATA || 9064 if (preexists && (it->state() == LookupIterator::DATA ||
9068 it->GetAccessors()->IsAccessorInfo())) { 9065 it->GetAccessors()->IsAccessorInfo())) {
9069 old_value = GetProperty(it).ToHandleChecked(); 9066 old_value = GetProperty(it).ToHandleChecked();
9070 } 9067 }
9071 } 9068 }
9072 9069
(...skipping 10840 matching lines...) Expand 10 before | Expand all | Expand 10 after
19913 if (cell->value() != *new_value) { 19910 if (cell->value() != *new_value) {
19914 cell->set_value(*new_value); 19911 cell->set_value(*new_value);
19915 Isolate* isolate = cell->GetIsolate(); 19912 Isolate* isolate = cell->GetIsolate();
19916 cell->dependent_code()->DeoptimizeDependentCodeGroup( 19913 cell->dependent_code()->DeoptimizeDependentCodeGroup(
19917 isolate, DependentCode::kPropertyCellChangedGroup); 19914 isolate, DependentCode::kPropertyCellChangedGroup);
19918 } 19915 }
19919 } 19916 }
19920 19917
19921 } // namespace internal 19918 } // namespace internal
19922 } // namespace v8 19919 } // namespace v8
OLDNEW
« src/heap/heap.cc ('K') | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698