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

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

Issue 1199493002: Revert relanded strong property access CL (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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
« no previous file with comments | « src/runtime/runtime-debug.cc ('k') | src/x64/code-stubs-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 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 LanguageMode language_mode) {
31 // Handle [] indexing on Strings 30 // Handle [] indexing on Strings
32 if (object->IsString() && 31 if (object->IsString() &&
33 index < static_cast<uint32_t>(String::cast(*object)->length())) { 32 index < static_cast<uint32_t>(String::cast(*object)->length())) {
34 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index); 33 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
35 if (!result->IsUndefined()) return result; 34 if (!result->IsUndefined()) return result;
36 } 35 }
37 36
38 return Object::GetElement(isolate, object, index, language_mode); 37 return Object::GetElement(isolate, object, index);
39 } 38 }
40 39
41 40
42 MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) { 41 MaybeHandle<Name> Runtime::ToName(Isolate* isolate, Handle<Object> key) {
43 if (key->IsName()) { 42 if (key->IsName()) {
44 return Handle<Name>::cast(key); 43 return Handle<Name>::cast(key);
45 } else { 44 } else {
46 Handle<Object> converted; 45 Handle<Object> converted;
47 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted, 46 ASSIGN_RETURN_ON_EXCEPTION(isolate, converted,
48 Execution::ToString(isolate, key), Name); 47 Execution::ToString(isolate, key), Name);
49 return Handle<Name>::cast(converted); 48 return Handle<Name>::cast(converted);
50 } 49 }
51 } 50 }
52 51
53 52
54 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, 53 MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
55 Handle<Object> object, 54 Handle<Object> object,
56 Handle<Object> key, 55 Handle<Object> key) {
57 LanguageMode language_mode) {
58 if (object->IsUndefined() || object->IsNull()) { 56 if (object->IsUndefined() || object->IsNull()) {
59 THROW_NEW_ERROR( 57 THROW_NEW_ERROR(
60 isolate, 58 isolate,
61 NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object), 59 NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object),
62 Object); 60 Object);
63 } 61 }
64 62
65 // Check if the given key is an array index. 63 // Check if the given key is an array index.
66 uint32_t index = 0; 64 uint32_t index = 0;
67 if (key->ToArrayIndex(&index)) { 65 if (key->ToArrayIndex(&index)) {
68 return GetElementOrCharAt(isolate, object, index, language_mode); 66 return GetElementOrCharAt(isolate, object, index);
69 } 67 }
70 68
71 // Convert the key to a name - possibly by calling back into JavaScript. 69 // Convert the key to a name - possibly by calling back into JavaScript.
72 Handle<Name> name; 70 Handle<Name> name;
73 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object); 71 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
74 72
75 // Check if the name is trivially convertible to an index and get 73 // Check if the name is trivially convertible to an index and get
76 // the element if so. 74 // the element if so.
77 // TODO(verwaest): Make sure GetProperty(LookupIterator*) can handle this, and 75 // TODO(verwaest): Make sure GetProperty(LookupIterator*) can handle this, and
78 // remove the special casing here. 76 // remove the special casing here.
79 if (name->AsArrayIndex(&index)) { 77 if (name->AsArrayIndex(&index)) {
80 return GetElementOrCharAt(isolate, object, index); 78 return GetElementOrCharAt(isolate, object, index);
81 } else { 79 } else {
82 return Object::GetProperty(object, name, language_mode); 80 return Object::GetProperty(object, name);
83 } 81 }
84 } 82 }
85 83
86 84
87 MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
88 Handle<Object> object, ElementsKind to_kind, Isolate* isolate) {
89 HandleScope scope(isolate);
90 if (!object->IsJSObject()) {
91 isolate->ThrowIllegalOperation();
92 return MaybeHandle<Object>();
93 }
94 ElementsKind from_kind =
95 Handle<JSObject>::cast(object)->map()->elements_kind();
96 if (Map::IsValidElementsTransition(from_kind, to_kind)) {
97 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
98 return object;
99 }
100 isolate->ThrowIllegalOperation();
101 return MaybeHandle<Object>();
102 }
103
104
105 MaybeHandle<Object> Runtime::KeyedGetObjectProperty(
106 Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
107 LanguageMode language_mode) {
108 // Fast cases for getting named properties of the receiver JSObject
109 // itself.
110 //
111 // The global proxy objects has to be excluded since LookupOwn on
112 // the global proxy object can return a valid result even though the
113 // global proxy object never has properties. This is the case
114 // because the global proxy object forwards everything to its hidden
115 // prototype including own lookups.
116 //
117 // Additionally, we need to make sure that we do not cache results
118 // for objects that require access checks.
119 if (receiver_obj->IsJSObject()) {
120 if (!receiver_obj->IsJSGlobalProxy() &&
121 !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
122 DisallowHeapAllocation no_allocation;
123 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
124 Handle<Name> key = Handle<Name>::cast(key_obj);
125 if (receiver->IsGlobalObject()) {
126 // Attempt dictionary lookup.
127 GlobalDictionary* dictionary = receiver->global_dictionary();
128 int entry = dictionary->FindEntry(key);
129 if (entry != GlobalDictionary::kNotFound) {
130 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
131 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
132 if (cell->property_details().type() == DATA) {
133 Object* value = cell->value();
134 if (!value->IsTheHole()) return Handle<Object>(value, isolate);
135 // If value is the hole (meaning, absent) do the general lookup.
136 }
137 }
138 } else if (!receiver->HasFastProperties()) {
139 // Attempt dictionary lookup.
140 NameDictionary* dictionary = receiver->property_dictionary();
141 int entry = dictionary->FindEntry(key);
142 if ((entry != NameDictionary::kNotFound) &&
143 (dictionary->DetailsAt(entry).type() == DATA)) {
144 Object* value = dictionary->ValueAt(entry);
145 return Handle<Object>(value, isolate);
146 }
147 }
148 } else if (key_obj->IsSmi()) {
149 // JSObject without a name key. If the key is a Smi, check for a
150 // definite out-of-bounds access to elements, which is a strong indicator
151 // that subsequent accesses will also call the runtime. Proactively
152 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
153 // doubles for those future calls in the case that the elements would
154 // become FAST_DOUBLE_ELEMENTS.
155 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
156 ElementsKind elements_kind = js_object->GetElementsKind();
157 if (IsFastDoubleElementsKind(elements_kind)) {
158 Handle<Smi> key = Handle<Smi>::cast(key_obj);
159 if (key->value() >= js_object->elements()->length()) {
160 if (IsFastHoleyElementsKind(elements_kind)) {
161 elements_kind = FAST_HOLEY_ELEMENTS;
162 } else {
163 elements_kind = FAST_ELEMENTS;
164 }
165 RETURN_ON_EXCEPTION(
166 isolate, TransitionElements(js_object, elements_kind, isolate),
167 Object);
168 }
169 } else {
170 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
171 !IsFastElementsKind(elements_kind));
172 }
173 }
174 } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
175 // Fast case for string indexing using [] with a smi index.
176 Handle<String> str = Handle<String>::cast(receiver_obj);
177 int index = Handle<Smi>::cast(key_obj)->value();
178 if (index >= 0 && index < str->length()) {
179 return GetCharAt(str, index);
180 }
181 }
182
183 // Fall back to GetObjectProperty.
184 return GetObjectProperty(isolate, receiver_obj, key_obj, language_mode);
185 }
186
187
188 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate, 85 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
189 Handle<Object> object, 86 Handle<Object> object,
190 Handle<Object> key, 87 Handle<Object> key,
191 Handle<Object> value, 88 Handle<Object> value,
192 LanguageMode language_mode) { 89 LanguageMode language_mode) {
193 if (object->IsUndefined() || object->IsNull()) { 90 if (object->IsUndefined() || object->IsNull()) {
194 THROW_NEW_ERROR( 91 THROW_NEW_ERROR(
195 isolate, 92 isolate,
196 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object), 93 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
197 Object); 94 Object);
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 !object->map()->is_observed() && !object->IsJSProxy()); 376 !object->map()->is_observed() && !object->IsJSProxy());
480 377
481 Handle<Object> result; 378 Handle<Object> result;
482 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object)); 379 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object));
483 return *result; 380 return *result;
484 } 381 }
485 382
486 383
487 RUNTIME_FUNCTION(Runtime_GetProperty) { 384 RUNTIME_FUNCTION(Runtime_GetProperty) {
488 HandleScope scope(isolate); 385 HandleScope scope(isolate);
489 DCHECK(args.length() == 3); 386 DCHECK(args.length() == 2);
490 387
491 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 388 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
492 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); 389 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
493 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2);
494
495 Handle<Object> result; 390 Handle<Object> result;
496 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 391 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
497 isolate, result, 392 isolate, result, Runtime::GetObjectProperty(isolate, object, key));
498 Runtime::GetObjectProperty(isolate, object, key, language_mode));
499 return *result; 393 return *result;
500 } 394 }
501 395
502 396
397 MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
398 Handle<Object> object, ElementsKind to_kind, Isolate* isolate) {
399 HandleScope scope(isolate);
400 if (!object->IsJSObject()) {
401 isolate->ThrowIllegalOperation();
402 return MaybeHandle<Object>();
403 }
404 ElementsKind from_kind =
405 Handle<JSObject>::cast(object)->map()->elements_kind();
406 if (Map::IsValidElementsTransition(from_kind, to_kind)) {
407 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
408 return object;
409 }
410 isolate->ThrowIllegalOperation();
411 return MaybeHandle<Object>();
412 }
413
414
415 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
503 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) { 416 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
504 HandleScope scope(isolate); 417 HandleScope scope(isolate);
505 DCHECK(args.length() == 3); 418 DCHECK(args.length() == 2);
506 419
507 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0); 420 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
508 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1); 421 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
509 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2);
510 422
423 // Fast cases for getting named properties of the receiver JSObject
424 // itself.
425 //
426 // The global proxy objects has to be excluded since LookupOwn on
427 // the global proxy object can return a valid result even though the
428 // global proxy object never has properties. This is the case
429 // because the global proxy object forwards everything to its hidden
430 // prototype including own lookups.
431 //
432 // Additionally, we need to make sure that we do not cache results
433 // for objects that require access checks.
434 if (receiver_obj->IsJSObject()) {
435 if (!receiver_obj->IsJSGlobalProxy() &&
436 !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
437 DisallowHeapAllocation no_allocation;
438 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
439 Handle<Name> key = Handle<Name>::cast(key_obj);
440 if (receiver->IsGlobalObject()) {
441 // Attempt dictionary lookup.
442 GlobalDictionary* dictionary = receiver->global_dictionary();
443 int entry = dictionary->FindEntry(key);
444 if (entry != GlobalDictionary::kNotFound) {
445 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
446 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
447 if (cell->property_details().type() == DATA) {
448 Object* value = cell->value();
449 if (!value->IsTheHole()) return value;
450 // If value is the hole (meaning, absent) do the general lookup.
451 }
452 }
453 } else if (!receiver->HasFastProperties()) {
454 // Attempt dictionary lookup.
455 NameDictionary* dictionary = receiver->property_dictionary();
456 int entry = dictionary->FindEntry(key);
457 if ((entry != NameDictionary::kNotFound) &&
458 (dictionary->DetailsAt(entry).type() == DATA)) {
459 Object* value = dictionary->ValueAt(entry);
460 return value;
461 }
462 }
463 } else if (key_obj->IsSmi()) {
464 // JSObject without a name key. If the key is a Smi, check for a
465 // definite out-of-bounds access to elements, which is a strong indicator
466 // that subsequent accesses will also call the runtime. Proactively
467 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
468 // doubles for those future calls in the case that the elements would
469 // become FAST_DOUBLE_ELEMENTS.
470 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
471 ElementsKind elements_kind = js_object->GetElementsKind();
472 if (IsFastDoubleElementsKind(elements_kind)) {
473 Handle<Smi> key = Handle<Smi>::cast(key_obj);
474 if (key->value() >= js_object->elements()->length()) {
475 if (IsFastHoleyElementsKind(elements_kind)) {
476 elements_kind = FAST_HOLEY_ELEMENTS;
477 } else {
478 elements_kind = FAST_ELEMENTS;
479 }
480 RETURN_FAILURE_ON_EXCEPTION(
481 isolate, TransitionElements(js_object, elements_kind, isolate));
482 }
483 } else {
484 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
485 !IsFastElementsKind(elements_kind));
486 }
487 }
488 } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
489 // Fast case for string indexing using [] with a smi index.
490 Handle<String> str = Handle<String>::cast(receiver_obj);
491 int index = args.smi_at(1);
492 if (index >= 0 && index < str->length()) {
493 return *GetCharAt(str, index);
494 }
495 }
496
497 // Fall back to GetObjectProperty.
511 Handle<Object> result; 498 Handle<Object> result;
512 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 499 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
513 isolate, result, Runtime::KeyedGetObjectProperty(isolate, receiver_obj, 500 isolate, result,
514 key_obj, language_mode)); 501 Runtime::GetObjectProperty(isolate, receiver_obj, key_obj));
515 return *result; 502 return *result;
516 } 503 }
517 504
518 505
519 RUNTIME_FUNCTION(Runtime_AddNamedProperty) { 506 RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
520 HandleScope scope(isolate); 507 HandleScope scope(isolate);
521 RUNTIME_ASSERT(args.length() == 4); 508 RUNTIME_ASSERT(args.length() == 4);
522 509
523 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); 510 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
524 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); 511 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
(...skipping 912 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); 1424 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1438 1425
1439 RETURN_FAILURE_ON_EXCEPTION( 1426 RETURN_FAILURE_ON_EXCEPTION(
1440 isolate, 1427 isolate,
1441 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), 1428 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1442 setter, attrs)); 1429 setter, attrs));
1443 return isolate->heap()->undefined_value(); 1430 return isolate->heap()->undefined_value();
1444 } 1431 }
1445 } // namespace internal 1432 } // namespace internal
1446 } // namespace v8 1433 } // namespace v8
OLDNEW
« no previous file with comments | « src/runtime/runtime-debug.cc ('k') | src/x64/code-stubs-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698