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

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

Issue 1185343005: Revert of Revert of [strong] Implement strong mode restrictions on property access (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) {
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
85 MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
86 Handle<Object> object,
87 Handle<Object> key,
88 Handle<Object> value,
89 LanguageMode language_mode) {
90 if (object->IsUndefined() || object->IsNull()) {
91 THROW_NEW_ERROR(
92 isolate,
93 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
94 Object);
95 }
96
97 // Check if the given key is an array index.
98 uint32_t index = 0;
99 if (key->ToArrayIndex(&index)) {
100 // TODO(verwaest): Support other objects as well.
101 if (!object->IsJSReceiver()) return value;
102 return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index,
103 value, language_mode);
104 }
105
106 Handle<Name> name;
107 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
108
109 LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
110 // TODO(verwaest): Support other objects as well.
111 if (it.IsElement() && !object->IsJSReceiver()) return value;
112 return Object::SetProperty(&it, value, language_mode,
113 Object::MAY_BE_STORE_FROM_KEYED);
114 }
115
116
117 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate,
118 Handle<Object> obj) {
119 // We don't expect access checks to be needed on JSProxy objects.
120 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
121 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
122 do {
123 if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() &&
124 !isolate->MayAccess(
125 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)))) {
126 isolate->ReportFailedAccessCheck(
127 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
128 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
129 return isolate->factory()->undefined_value();
130 }
131 iter.AdvanceIgnoringProxies();
132 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
133 return PrototypeIterator::GetCurrent(iter);
134 }
135 } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN));
136 return PrototypeIterator::GetCurrent(iter);
137 }
138
139
140 RUNTIME_FUNCTION(Runtime_GetPrototype) {
141 HandleScope scope(isolate);
142 DCHECK(args.length() == 1);
143 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
144 Handle<Object> result;
145 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
146 Runtime::GetPrototype(isolate, obj));
147 return *result;
148 }
149
150
151 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
152 HandleScope scope(isolate);
153 DCHECK(args.length() == 2);
154 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
155 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
156 DCHECK(!obj->IsAccessCheckNeeded());
157 DCHECK(!obj->map()->is_observed());
158 Handle<Object> result;
159 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
160 isolate, result, JSObject::SetPrototype(obj, prototype, false));
161 return *result;
162 }
163
164
165 RUNTIME_FUNCTION(Runtime_SetPrototype) {
166 HandleScope scope(isolate);
167 DCHECK(args.length() == 2);
168 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
169 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
170 if (obj->IsAccessCheckNeeded() && !isolate->MayAccess(obj)) {
171 isolate->ReportFailedAccessCheck(obj);
172 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
173 return isolate->heap()->undefined_value();
174 }
175 if (obj->map()->is_observed()) {
176 Handle<Object> old_value =
177 Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
178 Handle<Object> result;
179 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
180 isolate, result, JSObject::SetPrototype(obj, prototype, true));
181
182 Handle<Object> new_value =
183 Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
184 if (!new_value->SameValue(*old_value)) {
185 RETURN_FAILURE_ON_EXCEPTION(
186 isolate, JSObject::EnqueueChangeRecord(
187 obj, "setPrototype", isolate->factory()->proto_string(),
188 old_value));
189 }
190 return *result;
191 }
192 Handle<Object> result;
193 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
194 isolate, result, JSObject::SetPrototype(obj, prototype, true));
195 return *result;
196 }
197
198
199 RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) {
200 HandleScope shs(isolate);
201 DCHECK(args.length() == 2);
202 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
203 CONVERT_ARG_HANDLE_CHECKED(Object, O, 0);
204 CONVERT_ARG_HANDLE_CHECKED(Object, V, 1);
205 PrototypeIterator iter(isolate, V, PrototypeIterator::START_AT_RECEIVER);
206 while (true) {
207 iter.AdvanceIgnoringProxies();
208 if (iter.IsAtEnd()) return isolate->heap()->false_value();
209 if (iter.IsAtEnd(O)) return isolate->heap()->true_value();
210 }
211 }
212
213
214 // Enumerator used as indices into the array returned from GetOwnProperty
215 enum PropertyDescriptorIndices {
216 IS_ACCESSOR_INDEX,
217 VALUE_INDEX,
218 GETTER_INDEX,
219 SETTER_INDEX,
220 WRITABLE_INDEX,
221 ENUMERABLE_INDEX,
222 CONFIGURABLE_INDEX,
223 DESCRIPTOR_SIZE
224 };
225
226
227 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
228 Handle<JSObject> obj,
229 Handle<Name> name) {
230 Heap* heap = isolate->heap();
231 Factory* factory = isolate->factory();
232
233 PropertyAttributes attrs;
234 // Get attributes.
235 LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name,
236 LookupIterator::HIDDEN);
237 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
238
239 if (!maybe.IsJust()) return MaybeHandle<Object>();
240 attrs = maybe.FromJust();
241 if (attrs == ABSENT) return factory->undefined_value();
242
243 DCHECK(!isolate->has_pending_exception());
244 Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
245 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
246 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
247
248 bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR &&
249 it.GetAccessors()->IsAccessorPair();
250 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair));
251
252 if (is_accessor_pair) {
253 Handle<AccessorPair> accessors =
254 Handle<AccessorPair>::cast(it.GetAccessors());
255 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
256 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
257 elms->set(GETTER_INDEX, *getter);
258 elms->set(SETTER_INDEX, *setter);
259 } else {
260 Handle<Object> value;
261 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it),
262 Object);
263 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
264 elms->set(VALUE_INDEX, *value);
265 }
266
267 return factory->NewJSArrayWithElements(elms);
268 }
269
270
271 // Returns an array with the property description:
272 // if args[1] is not a property on args[0]
273 // returns undefined
274 // if args[1] is a data property on args[0]
275 // [false, value, Writeable, Enumerable, Configurable]
276 // if args[1] is an accessor on args[0]
277 // [true, GetFunction, SetFunction, Enumerable, Configurable]
278 RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
279 HandleScope scope(isolate);
280 DCHECK(args.length() == 2);
281 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
282 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
283 Handle<Object> result;
284 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
285 GetOwnProperty(isolate, obj, name));
286 return *result;
287 }
288
289
290 RUNTIME_FUNCTION(Runtime_PreventExtensions) {
291 HandleScope scope(isolate);
292 DCHECK(args.length() == 1);
293 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
294 Handle<Object> result;
295 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
296 JSObject::PreventExtensions(obj));
297 return *result;
298 }
299
300
301 RUNTIME_FUNCTION(Runtime_IsExtensible) {
302 SealHandleScope shs(isolate);
303 DCHECK(args.length() == 1);
304 CONVERT_ARG_CHECKED(JSObject, obj, 0);
305 return isolate->heap()->ToBoolean(obj->IsExtensible());
306 }
307
308
309 RUNTIME_FUNCTION(Runtime_DisableAccessChecks) {
310 HandleScope scope(isolate);
311 DCHECK(args.length() == 1);
312 CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
313 Handle<Map> old_map(object->map());
314 bool needs_access_checks = old_map->is_access_check_needed();
315 if (needs_access_checks) {
316 // Copy map so it won't interfere constructor's initial map.
317 Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks");
318 new_map->set_is_access_check_needed(false);
319 JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
320 }
321 return isolate->heap()->ToBoolean(needs_access_checks);
322 }
323
324
325 RUNTIME_FUNCTION(Runtime_EnableAccessChecks) {
326 HandleScope scope(isolate);
327 DCHECK(args.length() == 1);
328 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
329 Handle<Map> old_map(object->map());
330 RUNTIME_ASSERT(!old_map->is_access_check_needed());
331 // Copy map so it won't interfere constructor's initial map.
332 Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks");
333 new_map->set_is_access_check_needed(true);
334 JSObject::MigrateToMap(object, new_map);
335 return isolate->heap()->undefined_value();
336 }
337
338
339 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
340 HandleScope scope(isolate);
341 DCHECK(args.length() == 2);
342 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
343 CONVERT_SMI_ARG_CHECKED(properties, 1);
344 // Conservative upper limit to prevent fuzz tests from going OOM.
345 RUNTIME_ASSERT(properties <= 100000);
346 if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
347 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
348 "OptimizeForAdding");
349 }
350 return *object;
351 }
352
353
354 RUNTIME_FUNCTION(Runtime_ObjectFreeze) {
355 HandleScope scope(isolate);
356 DCHECK(args.length() == 1);
357 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
358
359 // %ObjectFreeze is a fast path and these cases are handled elsewhere.
360 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
361 !object->map()->is_observed() && !object->IsJSProxy());
362
363 Handle<Object> result;
364 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object));
365 return *result;
366 }
367
368
369 RUNTIME_FUNCTION(Runtime_ObjectSeal) {
370 HandleScope scope(isolate);
371 DCHECK(args.length() == 1);
372 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
373
374 // %ObjectSeal is a fast path and these cases are handled elsewhere.
375 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
376 !object->map()->is_observed() && !object->IsJSProxy());
377
378 Handle<Object> result;
379 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object));
380 return *result;
381 }
382
383
384 RUNTIME_FUNCTION(Runtime_GetProperty) {
385 HandleScope scope(isolate);
386 DCHECK(args.length() == 2);
387
388 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
389 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
390 Handle<Object> result;
391 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
392 isolate, result, Runtime::GetObjectProperty(isolate, object, key));
393 return *result;
394 }
395
396
397 MUST_USE_RESULT static MaybeHandle<Object> TransitionElements( 87 MUST_USE_RESULT static MaybeHandle<Object> TransitionElements(
398 Handle<Object> object, ElementsKind to_kind, Isolate* isolate) { 88 Handle<Object> object, ElementsKind to_kind, Isolate* isolate) {
399 HandleScope scope(isolate); 89 HandleScope scope(isolate);
400 if (!object->IsJSObject()) { 90 if (!object->IsJSObject()) {
401 isolate->ThrowIllegalOperation(); 91 isolate->ThrowIllegalOperation();
402 return MaybeHandle<Object>(); 92 return MaybeHandle<Object>();
403 } 93 }
404 ElementsKind from_kind = 94 ElementsKind from_kind =
405 Handle<JSObject>::cast(object)->map()->elements_kind(); 95 Handle<JSObject>::cast(object)->map()->elements_kind();
406 if (Map::IsValidElementsTransition(from_kind, to_kind)) { 96 if (Map::IsValidElementsTransition(from_kind, to_kind)) {
407 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind); 97 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
408 return object; 98 return object;
409 } 99 }
410 isolate->ThrowIllegalOperation(); 100 isolate->ThrowIllegalOperation();
411 return MaybeHandle<Object>(); 101 return MaybeHandle<Object>();
412 } 102 }
413 103
414 104
415 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric. 105 MaybeHandle<Object> Runtime::KeyedGetObjectProperty(
416 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) { 106 Isolate* isolate, Handle<Object> receiver_obj, Handle<Object> key_obj,
417 HandleScope scope(isolate); 107 LanguageMode language_mode) {
418 DCHECK(args.length() == 2);
419
420 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
421 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
422
423 // Fast cases for getting named properties of the receiver JSObject 108 // Fast cases for getting named properties of the receiver JSObject
424 // itself. 109 // itself.
425 // 110 //
426 // The global proxy objects has to be excluded since LookupOwn on 111 // The global proxy objects has to be excluded since LookupOwn on
427 // the global proxy object can return a valid result even though the 112 // the global proxy object can return a valid result even though the
428 // global proxy object never has properties. This is the case 113 // global proxy object never has properties. This is the case
429 // because the global proxy object forwards everything to its hidden 114 // because the global proxy object forwards everything to its hidden
430 // prototype including own lookups. 115 // prototype including own lookups.
431 // 116 //
432 // Additionally, we need to make sure that we do not cache results 117 // Additionally, we need to make sure that we do not cache results
433 // for objects that require access checks. 118 // for objects that require access checks.
434 if (receiver_obj->IsJSObject()) { 119 if (receiver_obj->IsJSObject()) {
435 if (!receiver_obj->IsJSGlobalProxy() && 120 if (!receiver_obj->IsJSGlobalProxy() &&
436 !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) { 121 !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
437 DisallowHeapAllocation no_allocation; 122 DisallowHeapAllocation no_allocation;
438 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj); 123 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
439 Handle<Name> key = Handle<Name>::cast(key_obj); 124 Handle<Name> key = Handle<Name>::cast(key_obj);
440 if (receiver->IsGlobalObject()) { 125 if (receiver->IsGlobalObject()) {
441 // Attempt dictionary lookup. 126 // Attempt dictionary lookup.
442 GlobalDictionary* dictionary = receiver->global_dictionary(); 127 GlobalDictionary* dictionary = receiver->global_dictionary();
443 int entry = dictionary->FindEntry(key); 128 int entry = dictionary->FindEntry(key);
444 if (entry != GlobalDictionary::kNotFound) { 129 if (entry != GlobalDictionary::kNotFound) {
445 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell()); 130 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
446 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry)); 131 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
447 if (cell->property_details().type() == DATA) { 132 if (cell->property_details().type() == DATA) {
448 Object* value = cell->value(); 133 Object* value = cell->value();
449 if (!value->IsTheHole()) return value; 134 if (!value->IsTheHole()) return Handle<Object>(value, isolate);
450 // If value is the hole (meaning, absent) do the general lookup. 135 // If value is the hole (meaning, absent) do the general lookup.
451 } 136 }
452 } 137 }
453 } else if (!receiver->HasFastProperties()) { 138 } else if (!receiver->HasFastProperties()) {
454 // Attempt dictionary lookup. 139 // Attempt dictionary lookup.
455 NameDictionary* dictionary = receiver->property_dictionary(); 140 NameDictionary* dictionary = receiver->property_dictionary();
456 int entry = dictionary->FindEntry(key); 141 int entry = dictionary->FindEntry(key);
457 if ((entry != NameDictionary::kNotFound) && 142 if ((entry != NameDictionary::kNotFound) &&
458 (dictionary->DetailsAt(entry).type() == DATA)) { 143 (dictionary->DetailsAt(entry).type() == DATA)) {
459 Object* value = dictionary->ValueAt(entry); 144 Object* value = dictionary->ValueAt(entry);
460 return value; 145 return Handle<Object>(value, isolate);
461 } 146 }
462 } 147 }
463 } else if (key_obj->IsSmi()) { 148 } else if (key_obj->IsSmi()) {
464 // JSObject without a name key. If the key is a Smi, check for a 149 // 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 150 // definite out-of-bounds access to elements, which is a strong indicator
466 // that subsequent accesses will also call the runtime. Proactively 151 // that subsequent accesses will also call the runtime. Proactively
467 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of 152 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
468 // doubles for those future calls in the case that the elements would 153 // doubles for those future calls in the case that the elements would
469 // become FAST_DOUBLE_ELEMENTS. 154 // become FAST_DOUBLE_ELEMENTS.
470 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj); 155 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
471 ElementsKind elements_kind = js_object->GetElementsKind(); 156 ElementsKind elements_kind = js_object->GetElementsKind();
472 if (IsFastDoubleElementsKind(elements_kind)) { 157 if (IsFastDoubleElementsKind(elements_kind)) {
473 Handle<Smi> key = Handle<Smi>::cast(key_obj); 158 Handle<Smi> key = Handle<Smi>::cast(key_obj);
474 if (key->value() >= js_object->elements()->length()) { 159 if (key->value() >= js_object->elements()->length()) {
475 if (IsFastHoleyElementsKind(elements_kind)) { 160 if (IsFastHoleyElementsKind(elements_kind)) {
476 elements_kind = FAST_HOLEY_ELEMENTS; 161 elements_kind = FAST_HOLEY_ELEMENTS;
477 } else { 162 } else {
478 elements_kind = FAST_ELEMENTS; 163 elements_kind = FAST_ELEMENTS;
479 } 164 }
480 RETURN_FAILURE_ON_EXCEPTION( 165 RETURN_ON_EXCEPTION(
481 isolate, TransitionElements(js_object, elements_kind, isolate)); 166 isolate, TransitionElements(js_object, elements_kind, isolate),
167 Object);
482 } 168 }
483 } else { 169 } else {
484 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) || 170 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
485 !IsFastElementsKind(elements_kind)); 171 !IsFastElementsKind(elements_kind));
486 } 172 }
487 } 173 }
488 } else if (receiver_obj->IsString() && key_obj->IsSmi()) { 174 } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
489 // Fast case for string indexing using [] with a smi index. 175 // Fast case for string indexing using [] with a smi index.
490 Handle<String> str = Handle<String>::cast(receiver_obj); 176 Handle<String> str = Handle<String>::cast(receiver_obj);
491 int index = args.smi_at(1); 177 int index = Handle<Smi>::cast(key_obj)->value();
492 if (index >= 0 && index < str->length()) { 178 if (index >= 0 && index < str->length()) {
493 return *GetCharAt(str, index); 179 return GetCharAt(str, index);
494 } 180 }
495 } 181 }
496 182
497 // Fall back to GetObjectProperty. 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,
189 Handle<Object> object,
190 Handle<Object> key,
191 Handle<Object> value,
192 LanguageMode language_mode) {
193 if (object->IsUndefined() || object->IsNull()) {
194 THROW_NEW_ERROR(
195 isolate,
196 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
197 Object);
198 }
199
200 // Check if the given key is an array index.
201 uint32_t index = 0;
202 if (key->ToArrayIndex(&index)) {
203 // TODO(verwaest): Support other objects as well.
204 if (!object->IsJSReceiver()) return value;
205 return JSReceiver::SetElement(Handle<JSReceiver>::cast(object), index,
206 value, language_mode);
207 }
208
209 Handle<Name> name;
210 ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
211
212 LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name);
213 // TODO(verwaest): Support other objects as well.
214 if (it.IsElement() && !object->IsJSReceiver()) return value;
215 return Object::SetProperty(&it, value, language_mode,
216 Object::MAY_BE_STORE_FROM_KEYED);
217 }
218
219
220 MaybeHandle<Object> Runtime::GetPrototype(Isolate* isolate,
221 Handle<Object> obj) {
222 // We don't expect access checks to be needed on JSProxy objects.
223 DCHECK(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
224 PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
225 do {
226 if (PrototypeIterator::GetCurrent(iter)->IsAccessCheckNeeded() &&
227 !isolate->MayAccess(
228 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)))) {
229 isolate->ReportFailedAccessCheck(
230 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
231 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
232 return isolate->factory()->undefined_value();
233 }
234 iter.AdvanceIgnoringProxies();
235 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
236 return PrototypeIterator::GetCurrent(iter);
237 }
238 } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN));
239 return PrototypeIterator::GetCurrent(iter);
240 }
241
242
243 RUNTIME_FUNCTION(Runtime_GetPrototype) {
244 HandleScope scope(isolate);
245 DCHECK(args.length() == 1);
246 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
247 Handle<Object> result;
248 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
249 Runtime::GetPrototype(isolate, obj));
250 return *result;
251 }
252
253
254 RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
255 HandleScope scope(isolate);
256 DCHECK(args.length() == 2);
257 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
258 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
259 DCHECK(!obj->IsAccessCheckNeeded());
260 DCHECK(!obj->map()->is_observed());
261 Handle<Object> result;
262 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
263 isolate, result, JSObject::SetPrototype(obj, prototype, false));
264 return *result;
265 }
266
267
268 RUNTIME_FUNCTION(Runtime_SetPrototype) {
269 HandleScope scope(isolate);
270 DCHECK(args.length() == 2);
271 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
272 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
273 if (obj->IsAccessCheckNeeded() && !isolate->MayAccess(obj)) {
274 isolate->ReportFailedAccessCheck(obj);
275 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
276 return isolate->heap()->undefined_value();
277 }
278 if (obj->map()->is_observed()) {
279 Handle<Object> old_value =
280 Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
281 Handle<Object> result;
282 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
283 isolate, result, JSObject::SetPrototype(obj, prototype, true));
284
285 Handle<Object> new_value =
286 Object::GetPrototypeSkipHiddenPrototypes(isolate, obj);
287 if (!new_value->SameValue(*old_value)) {
288 RETURN_FAILURE_ON_EXCEPTION(
289 isolate, JSObject::EnqueueChangeRecord(
290 obj, "setPrototype", isolate->factory()->proto_string(),
291 old_value));
292 }
293 return *result;
294 }
295 Handle<Object> result;
296 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
297 isolate, result, JSObject::SetPrototype(obj, prototype, true));
298 return *result;
299 }
300
301
302 RUNTIME_FUNCTION(Runtime_IsInPrototypeChain) {
303 HandleScope shs(isolate);
304 DCHECK(args.length() == 2);
305 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
306 CONVERT_ARG_HANDLE_CHECKED(Object, O, 0);
307 CONVERT_ARG_HANDLE_CHECKED(Object, V, 1);
308 PrototypeIterator iter(isolate, V, PrototypeIterator::START_AT_RECEIVER);
309 while (true) {
310 iter.AdvanceIgnoringProxies();
311 if (iter.IsAtEnd()) return isolate->heap()->false_value();
312 if (iter.IsAtEnd(O)) return isolate->heap()->true_value();
313 }
314 }
315
316
317 // Enumerator used as indices into the array returned from GetOwnProperty
318 enum PropertyDescriptorIndices {
319 IS_ACCESSOR_INDEX,
320 VALUE_INDEX,
321 GETTER_INDEX,
322 SETTER_INDEX,
323 WRITABLE_INDEX,
324 ENUMERABLE_INDEX,
325 CONFIGURABLE_INDEX,
326 DESCRIPTOR_SIZE
327 };
328
329
330 MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
331 Handle<JSObject> obj,
332 Handle<Name> name) {
333 Heap* heap = isolate->heap();
334 Factory* factory = isolate->factory();
335
336 PropertyAttributes attrs;
337 // Get attributes.
338 LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name,
339 LookupIterator::HIDDEN);
340 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
341
342 if (!maybe.IsJust()) return MaybeHandle<Object>();
343 attrs = maybe.FromJust();
344 if (attrs == ABSENT) return factory->undefined_value();
345
346 DCHECK(!isolate->has_pending_exception());
347 Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
348 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
349 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
350
351 bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR &&
352 it.GetAccessors()->IsAccessorPair();
353 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair));
354
355 if (is_accessor_pair) {
356 Handle<AccessorPair> accessors =
357 Handle<AccessorPair>::cast(it.GetAccessors());
358 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
359 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
360 elms->set(GETTER_INDEX, *getter);
361 elms->set(SETTER_INDEX, *setter);
362 } else {
363 Handle<Object> value;
364 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it),
365 Object);
366 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
367 elms->set(VALUE_INDEX, *value);
368 }
369
370 return factory->NewJSArrayWithElements(elms);
371 }
372
373
374 // Returns an array with the property description:
375 // if args[1] is not a property on args[0]
376 // returns undefined
377 // if args[1] is a data property on args[0]
378 // [false, value, Writeable, Enumerable, Configurable]
379 // if args[1] is an accessor on args[0]
380 // [true, GetFunction, SetFunction, Enumerable, Configurable]
381 RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
382 HandleScope scope(isolate);
383 DCHECK(args.length() == 2);
384 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
385 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
386 Handle<Object> result;
387 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
388 GetOwnProperty(isolate, obj, name));
389 return *result;
390 }
391
392
393 RUNTIME_FUNCTION(Runtime_PreventExtensions) {
394 HandleScope scope(isolate);
395 DCHECK(args.length() == 1);
396 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
397 Handle<Object> result;
398 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
399 JSObject::PreventExtensions(obj));
400 return *result;
401 }
402
403
404 RUNTIME_FUNCTION(Runtime_IsExtensible) {
405 SealHandleScope shs(isolate);
406 DCHECK(args.length() == 1);
407 CONVERT_ARG_CHECKED(JSObject, obj, 0);
408 return isolate->heap()->ToBoolean(obj->IsExtensible());
409 }
410
411
412 RUNTIME_FUNCTION(Runtime_DisableAccessChecks) {
413 HandleScope scope(isolate);
414 DCHECK(args.length() == 1);
415 CONVERT_ARG_HANDLE_CHECKED(HeapObject, object, 0);
416 Handle<Map> old_map(object->map());
417 bool needs_access_checks = old_map->is_access_check_needed();
418 if (needs_access_checks) {
419 // Copy map so it won't interfere constructor's initial map.
420 Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks");
421 new_map->set_is_access_check_needed(false);
422 JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
423 }
424 return isolate->heap()->ToBoolean(needs_access_checks);
425 }
426
427
428 RUNTIME_FUNCTION(Runtime_EnableAccessChecks) {
429 HandleScope scope(isolate);
430 DCHECK(args.length() == 1);
431 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
432 Handle<Map> old_map(object->map());
433 RUNTIME_ASSERT(!old_map->is_access_check_needed());
434 // Copy map so it won't interfere constructor's initial map.
435 Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks");
436 new_map->set_is_access_check_needed(true);
437 JSObject::MigrateToMap(object, new_map);
438 return isolate->heap()->undefined_value();
439 }
440
441
442 RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
443 HandleScope scope(isolate);
444 DCHECK(args.length() == 2);
445 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
446 CONVERT_SMI_ARG_CHECKED(properties, 1);
447 // Conservative upper limit to prevent fuzz tests from going OOM.
448 RUNTIME_ASSERT(properties <= 100000);
449 if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
450 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
451 "OptimizeForAdding");
452 }
453 return *object;
454 }
455
456
457 RUNTIME_FUNCTION(Runtime_ObjectFreeze) {
458 HandleScope scope(isolate);
459 DCHECK(args.length() == 1);
460 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
461
462 // %ObjectFreeze is a fast path and these cases are handled elsewhere.
463 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
464 !object->map()->is_observed() && !object->IsJSProxy());
465
466 Handle<Object> result;
467 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Freeze(object));
468 return *result;
469 }
470
471
472 RUNTIME_FUNCTION(Runtime_ObjectSeal) {
473 HandleScope scope(isolate);
474 DCHECK(args.length() == 1);
475 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
476
477 // %ObjectSeal is a fast path and these cases are handled elsewhere.
478 RUNTIME_ASSERT(!object->HasSloppyArgumentsElements() &&
479 !object->map()->is_observed() && !object->IsJSProxy());
480
481 Handle<Object> result;
482 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, JSObject::Seal(object));
483 return *result;
484 }
485
486
487 RUNTIME_FUNCTION(Runtime_GetProperty) {
488 HandleScope scope(isolate);
489 DCHECK(args.length() == 3);
490
491 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
492 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
493 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2);
494
498 Handle<Object> result; 495 Handle<Object> result;
499 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 496 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
500 isolate, result, 497 isolate, result,
501 Runtime::GetObjectProperty(isolate, receiver_obj, key_obj)); 498 Runtime::GetObjectProperty(isolate, object, key, language_mode));
502 return *result; 499 return *result;
503 } 500 }
504 501
502
503 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
504 HandleScope scope(isolate);
505 DCHECK(args.length() == 3);
506
507 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
508 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
509 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 2);
510
511 Handle<Object> result;
512 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
513 isolate, result, Runtime::KeyedGetObjectProperty(isolate, receiver_obj,
514 key_obj, language_mode));
515 return *result;
516 }
517
505 518
506 RUNTIME_FUNCTION(Runtime_AddNamedProperty) { 519 RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
507 HandleScope scope(isolate); 520 HandleScope scope(isolate);
508 RUNTIME_ASSERT(args.length() == 4); 521 RUNTIME_ASSERT(args.length() == 4);
509 522
510 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); 523 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
511 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); 524 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
512 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); 525 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
513 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); 526 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
514 527
(...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after
1424 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); 1437 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1425 1438
1426 RETURN_FAILURE_ON_EXCEPTION( 1439 RETURN_FAILURE_ON_EXCEPTION(
1427 isolate, 1440 isolate,
1428 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(), 1441 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1429 setter, attrs)); 1442 setter, attrs));
1430 return isolate->heap()->undefined_value(); 1443 return isolate->heap()->undefined_value();
1431 } 1444 }
1432 } // namespace internal 1445 } // namespace internal
1433 } // namespace v8 1446 } // 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