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

Side by Side Diff: src/runtime/runtime-object.cc

Issue 1168093002: [strong] Implement strong mode restrictions on property access (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix arm64 port Created 5 years, 6 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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/arguments.h" 7 #include "src/arguments.h"
8 #include "src/bootstrapper.h" 8 #include "src/bootstrapper.h"
9 #include "src/debug.h" 9 #include "src/debug.h"
10 #include "src/messages.h" 10 #include "src/messages.h"
11 #include "src/runtime/runtime.h" 11 #include "src/runtime/runtime.h"
12 #include "src/runtime/runtime-utils.h" 12 #include "src/runtime/runtime-utils.h"
13 13
14 namespace v8 { 14 namespace v8 {
15 namespace internal { 15 namespace internal {
16 16
17 // Returns a single character string where first character equals 17 // Returns a single character string where first character equals
18 // string->Get(index). 18 // string->Get(index).
19 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { 19 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
20 DCHECK_LT(index, static_cast<uint32_t>(string->length())); 20 DCHECK_LT(index, static_cast<uint32_t>(string->length()));
21 Factory* factory = string->GetIsolate()->factory(); 21 Factory* factory = string->GetIsolate()->factory();
22 return factory->LookupSingleCharacterStringFromCode( 22 return factory->LookupSingleCharacterStringFromCode(
23 String::Flatten(string)->Get(index)); 23 String::Flatten(string)->Get(index));
24 } 24 }
25 25
26 26
27 MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate, 27 MaybeHandle<Object> Runtime::GetElementOrCharAt(Isolate* isolate,
28 Handle<Object> object, 28 Handle<Object> object,
29 uint32_t index) { 29 uint32_t index,
30 Strength strength) {
30 // Handle [] indexing on Strings 31 // Handle [] indexing on Strings
31 if (object->IsString() && 32 if (object->IsString() &&
32 index < static_cast<uint32_t>(String::cast(*object)->length())) { 33 index < static_cast<uint32_t>(String::cast(*object)->length())) {
33 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index); 34 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
34 if (!result->IsUndefined()) return result; 35 if (!result->IsUndefined()) return result;
35 } 36 }
36 37
37 return Object::GetElement(isolate, object, index); 38 return Object::GetElement(isolate, object, index, strength);
38 } 39 }
39 40
40 41
41 MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) { 42 MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) {
42 if (key->IsName()) { 43 if (key->IsName()) {
43 return Handle<Name>::cast(key); 44 return Handle<Name>::cast(key);
44 } else { 45 } else {
45 Handle<Object> converted; 46 Handle<Object> converted;
46 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, 47 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted,
47 Execution::ToString(isolate, key), Name); 48 Execution::ToString(isolate, key), Name);
48 return Handle<Name>::cast(converted); 49 return Handle<Name>::cast(converted);
49 } 50 }
50 } 51 }
51 52
52 53
53 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, 54 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
54 Handle<Object> object, 55 Handle<Object> object,
55 Handle<Object> key) { 56 Handle<Object> key,
57 Strength strength) {
56 if (object->IsUndefined() || object->IsNull()) { 58 if (object->IsUndefined() || object->IsNull()) {
57 THROW_NEW_ERROR( 59 THROW_NEW_ERROR(
58 isolate, 60 isolate,
59 NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object), 61 NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object),
60 Object); 62 Object);
61 } 63 }
62 64
63 // Check if the given key is an array index. 65 // Check if the given key is an array index.
64 uint32_t index = 0; 66 uint32_t index = 0;
65 if (key->ToArrayIndex(&index)) { 67 if (key->ToArrayIndex(&index)) {
66 return GetElementOrCharAt(isolate, object, index); 68 return GetElementOrCharAt(isolate, object, index, strength);
67 } 69 }
68 70
69 // Convert the key to a name - possibly by calling back into JavaScript. 71 // Convert the key to a name - possibly by calling back into JavaScript.
70 Handle<Name> name; 72 Handle<Name> name;
71 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object); 73 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
72 74
73 // Check if the name is trivially convertible to an index and get 75 // Check if the name is trivially convertible to an index and get
74 // the element if so. 76 // the element if so.
75 if (name->AsArrayIndex(&index)) { 77 if (name->AsArrayIndex(&index)) {
76 return GetElementOrCharAt(isolate, object, index); 78 return GetElementOrCharAt(isolate, object, index);
77 } else { 79 } else {
78 return Object::GetProperty(object, name); 80 return Object::GetProperty(object, name, strength);
79 } 81 }
80 } 82 }
81 83
82 84
85 MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
86 Handle<Object> object, ElementsKind to_kind, Isolate* isolate) {
87 HandleScope scope(isolate);
88 if (!object->IsJSObject()) {
89 isolate->ThrowIllegalOperation();
90 return MaybeHandle<Object>();
91 }
92 ElementsKind from_kind =
93 Handle<JSObject>::cast(object)->map()->elements_kind();
94 if (Map::IsValidElementsTransition(from_kind, to_kind)) {
95 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
96 return object;
97 }
98 isolate->ThrowIllegalOperation();
99 return MaybeHandle<Object>();
100 }
101
102
103 MaybeHandle<Object> Runtime::KeyedGetObjectProperty(Isolate* isolate,
104 Handle<Object> receiver_obj,
105 Handle<Object> key_obj,
106 Strength strength) {
107 // Fast cases for getting named properties of the receiver JSObject
108 // itself.
109 //
110 // The global proxy objects has to be excluded since LookupOwn on
111 // the global proxy object can return a valid result even though the
112 // global proxy object never has properties. This is the case
113 // because the global proxy object forwards everything to its hidden
114 // prototype including own lookups.
115 //
116 // Additionally, we need to make sure that we do not cache results
117 // for objects that require access checks.
118 if (receiver_obj->IsJSObject()) {
119 if (!receiver_obj->IsJSGlobalProxy() &&
120 !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
121 DisallowHeapAllocation no_allocation;
122 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
123 Handle<Name> key = Handle<Name>::cast(key_obj);
124 if (receiver->IsGlobalObject()) {
125 // Attempt dictionary lookup.
126 GlobalDictionary* dictionary = receiver->global_dictionary();
127 int entry = dictionary->FindEntry(key);
128 if (entry != GlobalDictionary::kNotFound) {
129 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
130 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
131 if (cell->property_details().type() == DATA) {
132 Object* value = cell->value();
133 if (!value->IsTheHole()) return Handle<Object>(value, isolate);
134 // If value is the hole (meaning, absent) do the general lookup.
135 }
136 }
137 } else if (!receiver->HasFastProperties()) {
138 // Attempt dictionary lookup.
139 NameDictionary* dictionary = receiver->property_dictionary();
140 int entry = dictionary->FindEntry(key);
141 if ((entry != NameDictionary::kNotFound) &&
142 (dictionary->DetailsAt(entry).type() == DATA)) {
143 Object* value = dictionary->ValueAt(entry);
144 return Handle<Object>(value, isolate);
145 }
146 }
147 } else if (key_obj->IsSmi()) {
148 // JSObject without a name key. If the key is a Smi, check for a
149 // definite out-of-bounds access to elements, which is a strong indicator
150 // that subsequent accesses will also call the runtime. Proactively
151 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
152 // doubles for those future calls in the case that the elements would
153 // become FAST_DOUBLE_ELEMENTS.
154 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
155 ElementsKind elements_kind = js_object->GetElementsKind();
156 if (IsFastDoubleElementsKind(elements_kind)) {
157 Handle<Smi> key = Handle<Smi>::cast(key_obj);
158 if (key->value() >= js_object->elements()->length()) {
159 if (IsFastHoleyElementsKind(elements_kind)) {
160 elements_kind = FAST_HOLEY_ELEMENTS;
161 } else {
162 elements_kind = FAST_ELEMENTS;
163 }
164 RETURN_ON_EXCEPTION(
165 isolate, TransitionElements(js_object, elements_kind, isolate),
166 Object);
167 }
168 } else {
169 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
170 !IsFastElementsKind(elements_kind));
171 }
172 }
173 } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
174 // Fast case for string indexing using [] with a smi index.
175 Handle<String> str = Handle<String>::cast(receiver_obj);
176 int index = Handle<Smi>::cast(key_obj)->value();
177 if (index >= 0 && index < str->length()) {
178 return GetCharAt(str, index);
179 }
180 }
181
182 // Fall back to GetObjectProperty.
183 return GetObjectProperty(isolate, receiver_obj, key_obj, strength);
184 }
185
186
83 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate, 187 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
84 Handle<Object> object, 188 Handle<Object> object,
85 Handle<Object> key, 189 Handle<Object> key,
86 Handle<Object> value, 190 Handle<Object> value,
87 LanguageMode language_mode) { 191 LanguageMode language_mode) {
88 if (object->IsUndefined() || object->IsNull()) { 192 if (object->IsUndefined() || object->IsNull()) {
89 THROW_NEW_ERROR( 193 THROW_NEW_ERROR(
90 isolate, 194 isolate,
91 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object), 195 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
92 Object); 196 Object);
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 !object->map()->is_observed() && !object->IsJSProxy()); 596 !object->map()->is_observed() && !object->IsJSProxy());
493 597
494 Handle<Object> result; 598 Handle<Object> result;
495 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object)); 599 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object));
496 return *result; 600 return *result;
497 } 601 }
498 602
499 603
500 RUNTIME_FUNCTION(Runtime_GetProperty) { 604 RUNTIME_FUNCTION(Runtime_GetProperty) {
501 HandleScope scope(isolate); 605 HandleScope scope(isolate);
502 DCHECK(args.length() == 2); 606 DCHECK(args.length() == 3);
503 607
504 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 608 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
505 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); 609 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
610 CONVERT_BOOLEAN_ARG_CHECKED(strength, 2);
611
506 Handle<Object> result; 612 Handle<Object> result;
507 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 613 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
508 isolate, result, Runtime::GetObjectProperty(isolate, object, key)); 614 isolate, result,
615 Runtime::GetObjectProperty(isolate, object, key,
616 static_cast<Strength>(strength)));
509 return *result; 617 return *result;
510 } 618 }
511 619
512 620
513 MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
514 Handle<Object> object, ElementsKind to_kind, Isolate* isolate) {
515 HandleScope scope(isolate);
516 if (!object->IsJSObject()) {
517 isolate->ThrowIllegalOperation();
518 return MaybeHandle<Object>();
519 }
520 ElementsKind from_kind =
521 Handle<JSObject>::cast(object)->map()->elements_kind();
522 if (Map::IsValidElementsTransition(from_kind, to_kind)) {
523 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
524 return object;
525 }
526 isolate->ThrowIllegalOperation();
527 return MaybeHandle<Object>();
528 }
529
530
531 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric. 621 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
532 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) { 622 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
533 HandleScope scope(isolate); 623 HandleScope scope(isolate);
534 DCHECK(args.length() == 2); 624 DCHECK(args.length() == 3);
535 625
536 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0); 626 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
537 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1); 627 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
628 CONVERT_BOOLEAN_ARG_CHECKED(strength, 2);
538 629
539 // Fast cases for getting named properties of the receiver JSObject
540 // itself.
541 //
542 // The global proxy objects has to be excluded since LookupOwn on
543 // the global proxy object can return a valid result even though the
544 // global proxy object never has properties. This is the case
545 // because the global proxy object forwards everything to its hidden
546 // prototype including own lookups.
547 //
548 // Additionally, we need to make sure that we do not cache results
549 // for objects that require access checks.
550 if (receiver_obj->IsJSObject()) {
551 if (!receiver_obj->IsJSGlobalProxy() &&
552 !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
553 DisallowHeapAllocation no_allocation;
554 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
555 Handle<Name> key = Handle<Name>::cast(key_obj);
556 if (receiver->IsGlobalObject()) {
557 // Attempt dictionary lookup.
558 GlobalDictionary* dictionary = receiver->global_dictionary();
559 int entry = dictionary->FindEntry(key);
560 if (entry != GlobalDictionary::kNotFound) {
561 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
562 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
563 if (cell->property_details().type() == DATA) {
564 Object* value = cell->value();
565 if (!value->IsTheHole()) return value;
566 // If value is the hole (meaning, absent) do the general lookup.
567 }
568 }
569 } else if (!receiver->HasFastProperties()) {
570 // Attempt dictionary lookup.
571 NameDictionary* dictionary = receiver->property_dictionary();
572 int entry = dictionary->FindEntry(key);
573 if ((entry != NameDictionary::kNotFound) &&
574 (dictionary->DetailsAt(entry).type() == DATA)) {
575 Object* value = dictionary->ValueAt(entry);
576 return value;
577 }
578 }
579 } else if (key_obj->IsSmi()) {
580 // JSObject without a name key. If the key is a Smi, check for a
581 // definite out-of-bounds access to elements, which is a strong indicator
582 // that subsequent accesses will also call the runtime. Proactively
583 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
584 // doubles for those future calls in the case that the elements would
585 // become FAST_DOUBLE_ELEMENTS.
586 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
587 ElementsKind elements_kind = js_object->GetElementsKind();
588 if (IsFastDoubleElementsKind(elements_kind)) {
589 Handle<Smi> key = Handle<Smi>::cast(key_obj);
590 if (key->value() >= js_object->elements()->length()) {
591 if (IsFastHoleyElementsKind(elements_kind)) {
592 elements_kind = FAST_HOLEY_ELEMENTS;
593 } else {
594 elements_kind = FAST_ELEMENTS;
595 }
596 RETURN_FAILURE_ON_EXCEPTION(
597 isolate, TransitionElements(js_object, elements_kind, isolate));
598 }
599 } else {
600 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
601 !IsFastElementsKind(elements_kind));
602 }
603 }
604 } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
605 // Fast case for string indexing using [] with a smi index.
606 Handle<String> str = Handle<String>::cast(receiver_obj);
607 int index = args.smi_at(1);
608 if (index >= 0 && index < str->length()) {
609 return *GetCharAt(str, index);
610 }
611 }
612
613 // Fall back to GetObjectProperty.
614 Handle<Object> result; 630 Handle<Object> result;
615 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 631 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
616 isolate, result, 632 isolate, result,
617 Runtime::GetObjectProperty(isolate, receiver_obj, key_obj)); 633 Runtime::KeyedGetObjectProperty(isolate, receiver_obj, key_obj,
634 static_cast<Strength>(strength)));
618 return *result; 635 return *result;
619 } 636 }
620 637
621 638
622 RUNTIME_FUNCTION(Runtime_AddNamedProperty) { 639 RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
623 HandleScope scope(isolate); 640 HandleScope scope(isolate);
624 RUNTIME_ASSERT(args.length() == 4); 641 RUNTIME_ASSERT(args.length() == 4);
625 642
626 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); 643 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
627 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); 644 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
(...skipping 914 matching lines...) Expand 10 before | Expand all | Expand 10 after
1542 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); 1559 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1543 1560
1544 RETURN_FAILURE_ON_EXCEPTION( 1561 RETURN_FAILURE_ON_EXCEPTION(
1545 isolate, 1562 isolate,
1546 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), 1563 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1547 setter, attrs)); 1564 setter, attrs));
1548 return isolate->heap()->undefined_value(); 1565 return isolate->heap()->undefined_value();
1549 } 1566 }
1550 } // namespace internal 1567 } // namespace internal
1551 } // namespace v8 1568 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698