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

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

Issue 1199983002: [strong] Implement strong property access semantics (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: add TODOs Created 5 years, 5 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/builtins-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) {
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, language_mode);
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 LanguageMode language_mode) {
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, language_mode);
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 // TODO(verwaest): Make sure GetProperty(LookupIterator*) can handle this, and 77 // TODO(verwaest): Make sure GetProperty(LookupIterator*) can handle this, and
76 // remove the special casing here. 78 // remove the special casing here.
77 if (name->AsArrayIndex(&index)) { 79 if (name->AsArrayIndex(&index)) {
78 return GetElementOrCharAt(isolate, object, index); 80 return GetElementOrCharAt(isolate, object, index);
79 } else { 81 } else {
80 return Object::GetProperty(object, name); 82 return Object::GetProperty(object, name, language_mode);
81 } 83 }
82 } 84 }
83 85
84 86
87 MaybeHandle<Object> Runtime::KeyedGetObjectProperty(
88 Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
89 LanguageMode language_mode) {
90 // Fast cases for getting named properties of the receiver JSObject
91 // itself.
92 //
93 // The global proxy objects has to be excluded since LookupOwn on
94 // the global proxy object can return a valid result even though the
95 // global proxy object never has properties. This is the case
96 // because the global proxy object forwards everything to its hidden
97 // prototype including own lookups.
98 //
99 // Additionally, we need to make sure that we do not cache results
100 // for objects that require access checks.
101 if (receiver_obj->IsJSObject()) {
102 if (!receiver_obj->IsJSGlobalProxy() &&
103 !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
104 DisallowHeapAllocation no_allocation;
105 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
106 Handle<Name> key = Handle<Name>::cast(key_obj);
107 if (receiver->IsGlobalObject()) {
108 // Attempt dictionary lookup.
109 GlobalDictionary* dictionary = receiver->global_dictionary();
110 int entry = dictionary->FindEntry(key);
111 if (entry != GlobalDictionary::kNotFound) {
112 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
113 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
114 if (cell->property_details().type() == DATA) {
115 Object* value = cell->value();
116 if (!value->IsTheHole()) return Handle<Object>(value, isolate);
117 // If value is the hole (meaning, absent) do the general lookup.
118 }
119 }
120 } else if (!receiver->HasFastProperties()) {
121 // Attempt dictionary lookup.
122 NameDictionary* dictionary = receiver->property_dictionary();
123 int entry = dictionary->FindEntry(key);
124 if ((entry != NameDictionary::kNotFound) &&
125 (dictionary->DetailsAt(entry).type() == DATA)) {
126 Object* value = dictionary->ValueAt(entry);
127 return Handle<Object>(value, isolate);
128 }
129 }
130 } else if (key_obj->IsSmi()) {
131 // JSObject without a name key. If the key is a Smi, check for a
132 // definite out-of-bounds access to elements, which is a strong indicator
133 // that subsequent accesses will also call the runtime. Proactively
134 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
135 // doubles for those future calls in the case that the elements would
136 // become FAST_DOUBLE_ELEMENTS.
137 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
138 ElementsKind elements_kind = js_object->GetElementsKind();
139 if (IsFastDoubleElementsKind(elements_kind)) {
140 if (Smi::cast(*key_obj)->value() >= js_object->elements()->length()) {
141 elements_kind = IsFastHoleyElementsKind(elements_kind)
142 ? FAST_HOLEY_ELEMENTS
143 : FAST_ELEMENTS;
144 JSObject::TransitionElementsKind(js_object, elements_kind);
145 }
146 } else {
147 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
148 !IsFastElementsKind(elements_kind));
149 }
150 }
151 } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
152 // Fast case for string indexing using [] with a smi index.
153 Handle<String> str = Handle<String>::cast(receiver_obj);
154 int index = Handle<Smi>::cast(key_obj)->value();
155 if (index >= 0 && index < str->length()) {
156 return GetCharAt(str, index);
157 }
158 }
159
160 // Fall back to GetObjectProperty.
161 return GetObjectProperty(isolate, receiver_obj, key_obj, language_mode);
162 }
163
164
85 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate, 165 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
86 Handle<Object> object, 166 Handle<Object> object,
87 Handle<Object> key, 167 Handle<Object> key,
88 Handle<Object> value, 168 Handle<Object> value,
89 LanguageMode language_mode) { 169 LanguageMode language_mode) {
90 if (object->IsUndefined() || object->IsNull()) { 170 if (object->IsUndefined() || object->IsNull()) {
91 THROW_NEW_ERROR( 171 THROW_NEW_ERROR(
92 isolate, 172 isolate,
93 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object), 173 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
94 Object); 174 Object);
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 return *result; 460 return *result;
381 } 461 }
382 462
383 463
384 RUNTIME_FUNCTION(Runtime_GetProperty) { 464 RUNTIME_FUNCTION(Runtime_GetProperty) {
385 HandleScope scope(isolate); 465 HandleScope scope(isolate);
386 DCHECK(args.length() == 2); 466 DCHECK(args.length() == 2);
387 467
388 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 468 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
389 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); 469 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
470
390 Handle<Object> result; 471 Handle<Object> result;
391 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 472 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
392 isolate, result, Runtime::GetObjectProperty(isolate, object, key)); 473 isolate, result,
474 Runtime::GetObjectProperty(isolate, object, key, SLOPPY));
393 return *result; 475 return *result;
394 } 476 }
395 477
478
479 RUNTIME_FUNCTION(Runtime_GetPropertyStrong) {
480 HandleScope scope(isolate);
481 DCHECK(args.length() == 2);
482
483 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
484 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
485
486 Handle<Object> result;
487 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
488 isolate, result,
489 Runtime::GetObjectProperty(isolate, object, key, STRONG));
490 return *result;
491 }
492
396 493
397 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric. 494 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
398 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) { 495 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
399 HandleScope scope(isolate); 496 HandleScope scope(isolate);
400 DCHECK(args.length() == 2); 497 DCHECK(args.length() == 2);
401 498
402 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0); 499 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
403 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1); 500 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
404 501
405 // Fast cases for getting named properties of the receiver JSObject
406 // itself.
407 //
408 // The global proxy objects has to be excluded since LookupOwn on
409 // the global proxy object can return a valid result even though the
410 // global proxy object never has properties. This is the case
411 // because the global proxy object forwards everything to its hidden
412 // prototype including own lookups.
413 //
414 // Additionally, we need to make sure that we do not cache results
415 // for objects that require access checks.
416 if (receiver_obj->IsJSObject()) {
417 if (!receiver_obj->IsJSGlobalProxy() &&
418 !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
419 DisallowHeapAllocation no_allocation;
420 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
421 Handle<Name> key = Handle<Name>::cast(key_obj);
422 if (receiver->IsGlobalObject()) {
423 // Attempt dictionary lookup.
424 GlobalDictionary* dictionary = receiver->global_dictionary();
425 int entry = dictionary->FindEntry(key);
426 if (entry != GlobalDictionary::kNotFound) {
427 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
428 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
429 if (cell->property_details().type() == DATA) {
430 Object* value = cell->value();
431 if (!value->IsTheHole()) return value;
432 // If value is the hole (meaning, absent) do the general lookup.
433 }
434 }
435 } else if (!receiver->HasFastProperties()) {
436 // Attempt dictionary lookup.
437 NameDictionary* dictionary = receiver->property_dictionary();
438 int entry = dictionary->FindEntry(key);
439 if ((entry != NameDictionary::kNotFound) &&
440 (dictionary->DetailsAt(entry).type() == DATA)) {
441 Object* value = dictionary->ValueAt(entry);
442 return value;
443 }
444 }
445 } else if (key_obj->IsSmi()) {
446 // JSObject without a name key. If the key is a Smi, check for a
447 // definite out-of-bounds access to elements, which is a strong indicator
448 // that subsequent accesses will also call the runtime. Proactively
449 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
450 // doubles for those future calls in the case that the elements would
451 // become FAST_DOUBLE_ELEMENTS.
452 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
453 ElementsKind elements_kind = js_object->GetElementsKind();
454 if (IsFastDoubleElementsKind(elements_kind)) {
455 if (Smi::cast(*key_obj)->value() >= js_object->elements()->length()) {
456 elements_kind = IsFastHoleyElementsKind(elements_kind)
457 ? FAST_HOLEY_ELEMENTS
458 : FAST_ELEMENTS;
459 JSObject::TransitionElementsKind(js_object, elements_kind);
460 }
461 } else {
462 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
463 !IsFastElementsKind(elements_kind));
464 }
465 }
466 } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
467 // Fast case for string indexing using [] with a smi index.
468 Handle<String> str = Handle<String>::cast(receiver_obj);
469 int index = args.smi_at(1);
470 if (index >= 0 && index < str->length()) {
471 return *GetCharAt(str, index);
472 }
473 }
474
475 // Fall back to GetObjectProperty.
476 Handle<Object> result; 502 Handle<Object> result;
477 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 503 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
478 isolate, result, 504 isolate, result,
479 Runtime::GetObjectProperty(isolate, receiver_obj, key_obj)); 505 Runtime::KeyedGetObjectProperty(isolate, receiver_obj, key_obj, SLOPPY));
480 return *result; 506 return *result;
481 } 507 }
482 508
509
510 RUNTIME_FUNCTION(Runtime_KeyedGetPropertyStrong) {
511 HandleScope scope(isolate);
512 DCHECK(args.length() == 2);
513
514 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
515 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
516
517 Handle<Object> result;
518 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
519 isolate, result,
520 Runtime::KeyedGetObjectProperty(isolate, receiver_obj, key_obj, STRONG));
521 return *result;
522 }
523
483 524
484 RUNTIME_FUNCTION(Runtime_AddNamedProperty) { 525 RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
485 HandleScope scope(isolate); 526 HandleScope scope(isolate);
486 RUNTIME_ASSERT(args.length() == 4); 527 RUNTIME_ASSERT(args.length() == 4);
487 528
488 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); 529 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
489 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); 530 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
490 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); 531 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
491 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); 532 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
492 533
(...skipping 910 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); 1444 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1404 1445
1405 RETURN_FAILURE_ON_EXCEPTION( 1446 RETURN_FAILURE_ON_EXCEPTION(
1406 isolate, 1447 isolate,
1407 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), 1448 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1408 setter, attrs)); 1449 setter, attrs));
1409 return isolate->heap()->undefined_value(); 1450 return isolate->heap()->undefined_value();
1410 } 1451 }
1411 } // namespace internal 1452 } // namespace internal
1412 } // namespace v8 1453 } // namespace v8
OLDNEW
« no previous file with comments | « src/runtime/runtime-debug.cc ('k') | src/x64/builtins-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698