Chromium Code Reviews

Side by Side Diff: src/objects.cc

Issue 2915863004: [runtime] PreventExtensionsWithTransition: before adding the new (Closed)
Patch Set: [runtime] fix memory leak in PreventExtensionsWithTransition Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
« no previous file with comments | « src/objects.h ('k') | test/mjsunit/regress/regress-refreeze-same-map.js » ('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 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 <memory> 9 #include <memory>
10 #include <sstream> 10 #include <sstream>
(...skipping 7403 matching lines...)
7414 } 7414 }
7415 7415
7416 7416
7417 Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver, 7417 Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver,
7418 IntegrityLevel level, 7418 IntegrityLevel level,
7419 ShouldThrow should_throw) { 7419 ShouldThrow should_throw) {
7420 DCHECK(level == SEALED || level == FROZEN); 7420 DCHECK(level == SEALED || level == FROZEN);
7421 7421
7422 if (receiver->IsJSObject()) { 7422 if (receiver->IsJSObject()) {
7423 Handle<JSObject> object = Handle<JSObject>::cast(receiver); 7423 Handle<JSObject> object = Handle<JSObject>::cast(receiver);
7424
7425 // prevent memory leaks by not adding unnecessary transitions
7426 Maybe<bool> test = JSObject::TestIntegrityLevel(object, level);
7427 MAYBE_RETURN(test, Nothing<bool>());
7428 if (test.FromJust()) return Just(true);
7429
7424 if (!object->HasSloppyArgumentsElements()) { // Fast path. 7430 if (!object->HasSloppyArgumentsElements()) { // Fast path.
7425 if (level == SEALED) { 7431 if (level == SEALED) {
7426 return JSObject::PreventExtensionsWithTransition<SEALED>(object, 7432 return JSObject::PreventExtensionsWithTransition<SEALED>(object,
7427 should_throw); 7433 should_throw);
7428 } else { 7434 } else {
7429 return JSObject::PreventExtensionsWithTransition<FROZEN>(object, 7435 return JSObject::PreventExtensionsWithTransition<FROZEN>(object,
7430 should_throw); 7436 should_throw);
7431 } 7437 }
7432 } 7438 }
7433 } 7439 }
(...skipping 36 matching lines...)
7470 ? no_conf 7476 ? no_conf
7471 : no_conf_no_write; 7477 : no_conf_no_write;
7472 MAYBE_RETURN( 7478 MAYBE_RETURN(
7473 DefineOwnProperty(isolate, receiver, key, &desc, THROW_ON_ERROR), 7479 DefineOwnProperty(isolate, receiver, key, &desc, THROW_ON_ERROR),
7474 Nothing<bool>()); 7480 Nothing<bool>());
7475 } 7481 }
7476 } 7482 }
7477 return Just(true); 7483 return Just(true);
7478 } 7484 }
7479 7485
7480 7486 namespace {
7481 Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> object, 7487 Maybe<bool> GenericTestDescriptorsIntegrity(Handle<JSReceiver> object,
7482 IntegrityLevel level) { 7488 PropertyAttributes level) {
7483 DCHECK(level == SEALED || level == FROZEN);
7484 Isolate* isolate = object->GetIsolate(); 7489 Isolate* isolate = object->GetIsolate();
7485 7490
7486 Maybe<bool> extensible = JSReceiver::IsExtensible(object);
7487 MAYBE_RETURN(extensible, Nothing<bool>());
7488 if (extensible.FromJust()) return Just(false);
7489
7490 Handle<FixedArray> keys; 7491 Handle<FixedArray> keys;
7491 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 7492 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
7492 isolate, keys, JSReceiver::OwnPropertyKeys(object), Nothing<bool>()); 7493 isolate, keys, JSReceiver::OwnPropertyKeys(object), Nothing<bool>());
7493 7494
7494 for (int i = 0; i < keys->length(); ++i) { 7495 for (int i = 0; i < keys->length(); ++i) {
7495 Handle<Object> key(keys->get(i), isolate); 7496 Handle<Object> key(keys->get(i), isolate);
7496 PropertyDescriptor current_desc; 7497 PropertyDescriptor current_desc;
7497 Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor( 7498 Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
7498 isolate, object, key, &current_desc); 7499 isolate, object, key, &current_desc);
7499 MAYBE_RETURN(owned, Nothing<bool>()); 7500 MAYBE_RETURN(owned, Nothing<bool>());
7500 if (owned.FromJust()) { 7501 if (owned.FromJust()) {
7501 if (current_desc.configurable()) return Just(false); 7502 if (current_desc.configurable()) return Just(false);
7502 if (level == FROZEN && 7503 if (level == FROZEN &&
7503 PropertyDescriptor::IsDataDescriptor(&current_desc) && 7504 PropertyDescriptor::IsDataDescriptor(&current_desc) &&
7504 current_desc.writable()) { 7505 current_desc.writable()) {
7505 return Just(false); 7506 return Just(false);
7506 } 7507 }
7507 } 7508 }
7508 } 7509 }
7509 return Just(true); 7510 return Just(true);
7510 } 7511 }
7511 7512
7513 template <typename Dictionary>
7514 bool TestDictionaryPropertyIntegrity(Dictionary dict, Isolate* isolate,
7515 PropertyAttributes level) {
7516 DisallowHeapAllocation no_gc;
7517 uint32_t capacity = dict->Capacity();
7518 FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, {
Toon Verwaest 2017/06/20 08:43:23 Since you don't create handles here you don't need
kris.selden 2017/06/20 19:16:21 sorry, that was a bit of copy & paste from some ot
7519 Object* k = dict->KeyAt(j);
7520 if (!dict->IsKey(isolate, k)) continue;
Toon Verwaest 2017/06/20 08:43:23 You also need to check whether the key is "deleted
7521 PropertyDetails details = dict->DetailsAt(j);
7522 if (details.IsConfigurable()) return false;
7523 if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) {
7524 return false;
7525 }
7526 });
7527 return true;
7528 }
7529
7530 bool TestElementsIntegrityLevel(JSObject* object, PropertyAttributes level) {
7531 ElementsKind kind = object->GetElementsKind();
7532
7533 DCHECK(!IsSloppyArgumentsElementsKind(kind));
7534
7535 if (IsDictionaryElementsKind(kind)) {
7536 return TestDictionaryPropertyIntegrity(
7537 SeededNumberDictionary::cast(object->elements()), object->GetIsolate(),
7538 level);
7539 }
7540
7541 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
7542 // Only DICTIONARY_ELEMENTS and SLOW_SLOPPY_ARGUMENTS_ELEMENTS have
7543 // PropertyAttributes so just test if empty
7544 return accessor->NumberOfElements(object) == 0;
7545 }
7546
7547 bool TestFastPropertiesIntegrityLevel(Map* map, PropertyAttributes level) {
7548 DescriptorArray* descriptors = map->instance_descriptors();
7549 int number_of_own_descriptors = map->NumberOfOwnDescriptors();
7550 for (int i = 0; i < number_of_own_descriptors; i++) {
7551 PropertyDetails details = descriptors->GetDetails(i);
7552 if (details.IsConfigurable()) return false;
7553 if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) {
7554 return false;
7555 }
7556 }
7557 return true;
7558 }
7559
7560 bool TestPropertiesIntegrityLevel(JSObject* object, PropertyAttributes level) {
7561 if (object->HasFastProperties()) {
7562 return TestFastPropertiesIntegrityLevel(object->map(), level);
7563 }
7564
7565 if (object->IsJSGlobalObject()) {
7566 return TestDictionaryPropertyIntegrity(object->global_dictionary(),
7567 object->GetIsolate(), level);
7568 }
7569
7570 return TestDictionaryPropertyIntegrity(object->property_dictionary(),
7571 object->GetIsolate(), level);
7572 }
7573
7574 } // namespace
7575
7576 Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> object,
7577 IntegrityLevel level) {
7578 if (object->IsJSObject()) {
Toon Verwaest 2017/06/20 08:43:23 object->instance_type() > LAST_CUSTOM_ELEMENTS_REC
7579 return JSObject::TestIntegrityLevel(Handle<JSObject>::cast(object), level);
7580 }
7581
7582 DCHECK(level == SEALED || level == FROZEN);
7583
7584 Maybe<bool> extensible = JSReceiver::IsExtensible(object);
7585 MAYBE_RETURN(extensible, Nothing<bool>());
7586 if (extensible.FromJust()) return Just(false);
7587
7588 return GenericTestDescriptorsIntegrity(object, level);
7589 }
7590
7591 Maybe<bool> JSObject::TestIntegrityLevel(Handle<JSObject> object,
7592 IntegrityLevel level) {
7593 DCHECK(level == SEALED || level == FROZEN);
7594
7595 Isolate* isolate = object->GetIsolate();
7596 if (object->IsAccessCheckNeeded() &&
Toon Verwaest 2017/06/20 08:43:23 If you only support > LAST_CUSTOM_ELEMENTS_RECEIVE
7597 !isolate->MayAccess(handle(isolate->context()), object)) {
7598 return Just(false);
7599 }
7600
7601 if (object->IsJSGlobalProxy()) {
Toon Verwaest 2017/06/20 08:43:23 And in that case you can also drop this.
7602 PrototypeIterator iter(isolate, object);
7603 if (iter.IsAtEnd()) return Just(true);
7604 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
7605 return TestIntegrityLevel(PrototypeIterator::GetCurrent<JSObject>(iter),
7606 level);
7607 }
7608
7609 if (object->map()->is_extensible()) return Just(false);
7610
7611 if (object->HasSloppyArgumentsElements()) {
7612 return GenericTestDescriptorsIntegrity(Handle<JSReceiver>::cast(object),
7613 level);
7614 }
7615
7616 if (!TestElementsIntegrityLevel(*object, level)) {
Toon Verwaest 2017/06/20 08:43:23 return Just(!object->map()->is_extensible() &&
7617 return Just(false);
7618 }
7619
7620 if (!TestPropertiesIntegrityLevel(*object, level)) {
7621 return Just(false);
7622 }
7623
7624 return Just(true);
7625 }
7512 7626
7513 Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object, 7627 Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object,
7514 ShouldThrow should_throw) { 7628 ShouldThrow should_throw) {
7515 if (object->IsJSProxy()) { 7629 if (object->IsJSProxy()) {
7516 return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object), 7630 return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object),
7517 should_throw); 7631 should_throw);
7518 } 7632 }
7519 DCHECK(object->IsJSObject()); 7633 DCHECK(object->IsJSObject());
7520 return JSObject::PreventExtensions(Handle<JSObject>::cast(object), 7634 return JSObject::PreventExtensions(Handle<JSObject>::cast(object),
7521 should_throw); 7635 should_throw);
(...skipping 12651 matching lines...)
20173 // not 20287 // not
20174 // depend on this. 20288 // depend on this.
20175 return DICTIONARY_ELEMENTS; 20289 return DICTIONARY_ELEMENTS;
20176 } 20290 }
20177 DCHECK_LE(kind, LAST_ELEMENTS_KIND); 20291 DCHECK_LE(kind, LAST_ELEMENTS_KIND);
20178 return kind; 20292 return kind;
20179 } 20293 }
20180 } 20294 }
20181 } // namespace internal 20295 } // namespace internal
20182 } // namespace v8 20296 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | test/mjsunit/regress/regress-refreeze-same-map.js » ('j') | no next file with comments »

Powered by Google App Engine