blob: 75ddb7bc22b66e7d2efc11ded838b6e9e81d1ac2 [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// 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
3// found in the LICENSE file.
4
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/runtime/runtime-utils.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006
7#include "src/arguments.h"
8#include "src/bootstrapper.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/debug/debug.h"
10#include "src/isolate-inl.h"
11#include "src/messages.h"
12#include "src/property-descriptor.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013#include "src/runtime/runtime.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040014
15namespace v8 {
16namespace internal {
17
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018
19MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
20 Handle<Object> object,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021 Handle<Object> key,
22 LanguageMode language_mode) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023 if (object->IsUndefined() || object->IsNull()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024 THROW_NEW_ERROR(
25 isolate,
26 NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object),
27 Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040028 }
29
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030 bool success = false;
31 LookupIterator it =
32 LookupIterator::PropertyOrElement(isolate, object, key, &success);
33 if (!success) return MaybeHandle<Object>();
34
35 return Object::GetProperty(&it, language_mode);
36}
37
38
39static MaybeHandle<Object> KeyedGetObjectProperty(Isolate* isolate,
40 Handle<Object> receiver_obj,
41 Handle<Object> key_obj,
42 LanguageMode language_mode) {
43 // Fast cases for getting named properties of the receiver JSObject
44 // itself.
45 //
46 // The global proxy objects has to be excluded since LookupOwn on
47 // the global proxy object can return a valid result even though the
48 // global proxy object never has properties. This is the case
49 // because the global proxy object forwards everything to its hidden
50 // prototype including own lookups.
51 //
52 // Additionally, we need to make sure that we do not cache results
53 // for objects that require access checks.
54 if (receiver_obj->IsJSObject()) {
55 if (!receiver_obj->IsJSGlobalProxy() &&
56 !receiver_obj->IsAccessCheckNeeded() && key_obj->IsName()) {
57 DisallowHeapAllocation no_allocation;
58 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj);
59 Handle<Name> key = Handle<Name>::cast(key_obj);
60 if (receiver->IsJSGlobalObject()) {
61 // Attempt dictionary lookup.
62 GlobalDictionary* dictionary = receiver->global_dictionary();
63 int entry = dictionary->FindEntry(key);
64 if (entry != GlobalDictionary::kNotFound) {
65 DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
66 PropertyCell* cell = PropertyCell::cast(dictionary->ValueAt(entry));
67 if (cell->property_details().type() == DATA) {
68 Object* value = cell->value();
69 if (!value->IsTheHole()) return Handle<Object>(value, isolate);
70 // If value is the hole (meaning, absent) do the general lookup.
71 }
72 }
73 } else if (!receiver->HasFastProperties()) {
74 // Attempt dictionary lookup.
75 NameDictionary* dictionary = receiver->property_dictionary();
76 int entry = dictionary->FindEntry(key);
77 if ((entry != NameDictionary::kNotFound) &&
78 (dictionary->DetailsAt(entry).type() == DATA)) {
79 Object* value = dictionary->ValueAt(entry);
80 return Handle<Object>(value, isolate);
81 }
82 }
83 } else if (key_obj->IsSmi()) {
84 // JSObject without a name key. If the key is a Smi, check for a
85 // definite out-of-bounds access to elements, which is a strong indicator
86 // that subsequent accesses will also call the runtime. Proactively
87 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
88 // doubles for those future calls in the case that the elements would
89 // become FAST_DOUBLE_ELEMENTS.
90 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj);
91 ElementsKind elements_kind = js_object->GetElementsKind();
92 if (IsFastDoubleElementsKind(elements_kind)) {
93 if (Smi::cast(*key_obj)->value() >= js_object->elements()->length()) {
94 elements_kind = IsFastHoleyElementsKind(elements_kind)
95 ? FAST_HOLEY_ELEMENTS
96 : FAST_ELEMENTS;
97 JSObject::TransitionElementsKind(js_object, elements_kind);
98 }
99 } else {
100 DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
101 !IsFastElementsKind(elements_kind));
102 }
103 }
104 } else if (receiver_obj->IsString() && key_obj->IsSmi()) {
105 // Fast case for string indexing using [] with a smi index.
106 Handle<String> str = Handle<String>::cast(receiver_obj);
107 int index = Handle<Smi>::cast(key_obj)->value();
108 if (index >= 0 && index < str->length()) {
109 Factory* factory = isolate->factory();
110 return factory->LookupSingleCharacterStringFromCode(
111 String::Flatten(str)->Get(index));
112 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400113 }
114
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 // Fall back to GetObjectProperty.
116 return Runtime::GetObjectProperty(isolate, receiver_obj, key_obj,
117 language_mode);
118}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400119
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120
121Maybe<bool> Runtime::DeleteObjectProperty(Isolate* isolate,
122 Handle<JSReceiver> receiver,
123 Handle<Object> key,
124 LanguageMode language_mode) {
125 bool success = false;
126 LookupIterator it = LookupIterator::PropertyOrElement(
127 isolate, receiver, key, &success, LookupIterator::HIDDEN);
128 if (!success) return Nothing<bool>();
129
130 return JSReceiver::DeleteProperty(&it, language_mode);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400131}
132
133
134MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate,
135 Handle<Object> object,
136 Handle<Object> key,
137 Handle<Object> value,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 LanguageMode language_mode) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400139 if (object->IsUndefined() || object->IsNull()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 THROW_NEW_ERROR(
141 isolate,
142 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object),
143 Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400144 }
145
146 // Check if the given key is an array index.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 bool success = false;
148 LookupIterator it =
149 LookupIterator::PropertyOrElement(isolate, object, key, &success);
150 if (!success) return MaybeHandle<Object>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 MAYBE_RETURN_NULL(Object::SetProperty(&it, value, language_mode,
153 Object::MAY_BE_STORE_FROM_KEYED));
154 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400155}
156
157
158RUNTIME_FUNCTION(Runtime_GetPrototype) {
159 HandleScope scope(isolate);
160 DCHECK(args.length() == 1);
161 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162 Handle<Object> prototype;
163 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype,
164 Object::GetPrototype(isolate, obj));
165 return *prototype;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400166}
167
168
169RUNTIME_FUNCTION(Runtime_InternalSetPrototype) {
170 HandleScope scope(isolate);
171 DCHECK(args.length() == 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400173 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 MAYBE_RETURN(
175 JSReceiver::SetPrototype(obj, prototype, false, Object::THROW_ON_ERROR),
176 isolate->heap()->exception());
177 return *obj;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400178}
179
180
181RUNTIME_FUNCTION(Runtime_SetPrototype) {
182 HandleScope scope(isolate);
183 DCHECK(args.length() == 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400185 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 MAYBE_RETURN(
187 JSReceiver::SetPrototype(obj, prototype, true, Object::THROW_ON_ERROR),
188 isolate->heap()->exception());
189 return *obj;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400190}
191
192
193// Enumerator used as indices into the array returned from GetOwnProperty
194enum PropertyDescriptorIndices {
195 IS_ACCESSOR_INDEX,
196 VALUE_INDEX,
197 GETTER_INDEX,
198 SETTER_INDEX,
199 WRITABLE_INDEX,
200 ENUMERABLE_INDEX,
201 CONFIGURABLE_INDEX,
202 DESCRIPTOR_SIZE
203};
204
205
206MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
207 Handle<JSObject> obj,
208 Handle<Name> name) {
209 Heap* heap = isolate->heap();
210 Factory* factory = isolate->factory();
211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 // Get attributes.
213 LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name,
214 LookupIterator::HIDDEN);
215 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400216
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217 if (!maybe.IsJust()) return MaybeHandle<Object>();
218 PropertyAttributes attrs = maybe.FromJust();
219 if (attrs == ABSENT) return factory->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400220
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400221 DCHECK(!isolate->has_pending_exception());
222 Handle<FixedArray> elms = factory->NewFixedArray(DESCRIPTOR_SIZE);
223 elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
224 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400225
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000226 bool is_accessor_pair = it.state() == LookupIterator::ACCESSOR &&
227 it.GetAccessors()->IsAccessorPair();
228 elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(is_accessor_pair));
229
230 if (is_accessor_pair) {
231 Handle<AccessorPair> accessors =
232 Handle<AccessorPair>::cast(it.GetAccessors());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400233 Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
234 Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
235 elms->set(GETTER_INDEX, *getter);
236 elms->set(SETTER_INDEX, *setter);
237 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 Handle<Object> value;
239 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it),
240 Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400241 elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
242 elms->set(VALUE_INDEX, *value);
243 }
244
245 return factory->NewJSArrayWithElements(elms);
246}
247
248
249// Returns an array with the property description:
250// if args[1] is not a property on args[0]
251// returns undefined
252// if args[1] is a data property on args[0]
253// [false, value, Writeable, Enumerable, Configurable]
254// if args[1] is an accessor on args[0]
255// [true, GetFunction, SetFunction, Enumerable, Configurable]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256// TODO(jkummerow): Deprecated. Remove all callers and delete.
257RUNTIME_FUNCTION(Runtime_GetOwnProperty_Legacy) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400258 HandleScope scope(isolate);
259 DCHECK(args.length() == 2);
260 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
261 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
262 Handle<Object> result;
263 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
264 GetOwnProperty(isolate, obj, name));
265 return *result;
266}
267
268
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000269// ES6 19.1.2.6
270RUNTIME_FUNCTION(Runtime_GetOwnProperty) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400271 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 DCHECK(args.length() == 2);
273 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
274 CONVERT_ARG_HANDLE_CHECKED(Object, raw_name, 1);
275 // 1. Let obj be ? ToObject(O).
276 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
277 Execution::ToObject(isolate, object));
278 // 2. Let key be ? ToPropertyKey(P).
279 Handle<Name> key;
280 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
281 Object::ToName(isolate, raw_name));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400282
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000283 // 3. Let desc be ? obj.[[GetOwnProperty]](key).
284 PropertyDescriptor desc;
285 Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
286 isolate, Handle<JSReceiver>::cast(object), key, &desc);
287 MAYBE_RETURN(found, isolate->heap()->exception());
288 // 4. Return FromPropertyDescriptor(desc).
289 if (!found.FromJust()) return isolate->heap()->undefined_value();
290 return *desc.ToObject(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400291}
292
293
294RUNTIME_FUNCTION(Runtime_OptimizeObjectForAddingMultipleProperties) {
295 HandleScope scope(isolate);
296 DCHECK(args.length() == 2);
297 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
298 CONVERT_SMI_ARG_CHECKED(properties, 1);
299 // Conservative upper limit to prevent fuzz tests from going OOM.
300 RUNTIME_ASSERT(properties <= 100000);
301 if (object->HasFastProperties() && !object->IsJSGlobalProxy()) {
302 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties,
303 "OptimizeForAdding");
304 }
305 return *object;
306}
307
308
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309RUNTIME_FUNCTION(Runtime_LoadGlobalViaContext) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400310 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 DCHECK_EQ(1, args.length());
312 CONVERT_SMI_ARG_CHECKED(slot, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400313
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000314 // Go up context chain to the script context.
315 Handle<Context> script_context(isolate->context()->script_context(), isolate);
316 DCHECK(script_context->IsScriptContext());
317 DCHECK(script_context->get(slot)->IsPropertyCell());
318
319 // Lookup the named property on the global object.
320 Handle<ScopeInfo> scope_info(script_context->scope_info(), isolate);
321 Handle<Name> name(scope_info->ContextSlotName(slot), isolate);
322 Handle<JSGlobalObject> global_object(script_context->global_object(),
323 isolate);
324 LookupIterator it(global_object, name, LookupIterator::HIDDEN);
325
326 // Switch to fast mode only if there is a data property and it's not on
327 // a hidden prototype.
328 if (it.state() == LookupIterator::DATA &&
329 it.GetHolder<Object>().is_identical_to(global_object)) {
330 // Now update the cell in the script context.
331 Handle<PropertyCell> cell = it.GetPropertyCell();
332 script_context->set(slot, *cell);
333 } else {
334 // This is not a fast case, so keep this access in a slow mode.
335 // Store empty_property_cell here to release the outdated property cell.
336 script_context->set(slot, isolate->heap()->empty_property_cell());
337 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400338
339 Handle<Object> result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400341 return *result;
342}
343
344
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000345namespace {
346
347Object* StoreGlobalViaContext(Isolate* isolate, int slot, Handle<Object> value,
348 LanguageMode language_mode) {
349 // Go up context chain to the script context.
350 Handle<Context> script_context(isolate->context()->script_context(), isolate);
351 DCHECK(script_context->IsScriptContext());
352 DCHECK(script_context->get(slot)->IsPropertyCell());
353
354 // Lookup the named property on the global object.
355 Handle<ScopeInfo> scope_info(script_context->scope_info(), isolate);
356 Handle<Name> name(scope_info->ContextSlotName(slot), isolate);
357 Handle<JSGlobalObject> global_object(script_context->global_object(),
358 isolate);
359 LookupIterator it(global_object, name, LookupIterator::HIDDEN);
360
361 // Switch to fast mode only if there is a data property and it's not on
362 // a hidden prototype.
363 if (it.state() == LookupIterator::DATA &&
364 it.GetHolder<Object>().is_identical_to(global_object)) {
365 // Now update cell in the script context.
366 Handle<PropertyCell> cell = it.GetPropertyCell();
367 script_context->set(slot, *cell);
368 } else {
369 // This is not a fast case, so keep this access in a slow mode.
370 // Store empty_property_cell here to release the outdated property cell.
371 script_context->set(slot, isolate->heap()->empty_property_cell());
372 }
373
374 MAYBE_RETURN(Object::SetProperty(&it, value, language_mode,
375 Object::CERTAINLY_NOT_STORE_FROM_KEYED),
376 isolate->heap()->exception());
377 return *value;
378}
379
380} // namespace
381
382
383RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Sloppy) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400384 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385 DCHECK_EQ(2, args.length());
386 CONVERT_SMI_ARG_CHECKED(slot, 0);
387 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400388
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000389 return StoreGlobalViaContext(isolate, slot, value, SLOPPY);
390}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400391
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392
393RUNTIME_FUNCTION(Runtime_StoreGlobalViaContext_Strict) {
394 HandleScope scope(isolate);
395 DCHECK_EQ(2, args.length());
396 CONVERT_SMI_ARG_CHECKED(slot, 0);
397 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
398
399 return StoreGlobalViaContext(isolate, slot, value, STRICT);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400400}
401
402
403RUNTIME_FUNCTION(Runtime_GetProperty) {
404 HandleScope scope(isolate);
405 DCHECK(args.length() == 2);
406
407 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
408 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000409
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400410 Handle<Object> result;
411 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 isolate, result,
413 Runtime::GetObjectProperty(isolate, object, key, SLOPPY));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400414 return *result;
415}
416
417
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000418RUNTIME_FUNCTION(Runtime_GetPropertyStrong) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400419 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420 DCHECK(args.length() == 2);
421
422 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
423 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
424
425 Handle<Object> result;
426 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
427 isolate, result,
428 Runtime::GetObjectProperty(isolate, object, key, STRONG));
429 return *result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400430}
431
432
433// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
434RUNTIME_FUNCTION(Runtime_KeyedGetProperty) {
435 HandleScope scope(isolate);
436 DCHECK(args.length() == 2);
437
438 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
439 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
440
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400441 Handle<Object> result;
442 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
443 isolate, result,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444 KeyedGetObjectProperty(isolate, receiver_obj, key_obj, SLOPPY));
445 return *result;
446}
447
448
449RUNTIME_FUNCTION(Runtime_KeyedGetPropertyStrong) {
450 HandleScope scope(isolate);
451 DCHECK(args.length() == 2);
452
453 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0);
454 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1);
455
456 Handle<Object> result;
457 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
458 isolate, result,
459 KeyedGetObjectProperty(isolate, receiver_obj, key_obj, STRONG));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400460 return *result;
461}
462
463
464RUNTIME_FUNCTION(Runtime_AddNamedProperty) {
465 HandleScope scope(isolate);
466 RUNTIME_ASSERT(args.length() == 4);
467
468 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400470 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000471 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400472
473#ifdef DEBUG
474 uint32_t index = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475 DCHECK(!name->ToArrayIndex(&index));
476 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400477 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478 if (!maybe.IsJust()) return isolate->heap()->exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400479 RUNTIME_ASSERT(!it.IsFound());
480#endif
481
482 Handle<Object> result;
483 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
484 isolate, result,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000485 JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, attrs));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400486 return *result;
487}
488
489
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490// Adds an element to an array.
491// This is used to create an indexed data property into an array.
492RUNTIME_FUNCTION(Runtime_AddElement) {
493 HandleScope scope(isolate);
494 RUNTIME_ASSERT(args.length() == 3);
495
496 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
497 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
498 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
499
500 uint32_t index = 0;
501 CHECK(key->ToArrayIndex(&index));
502
503#ifdef DEBUG
504 LookupIterator it(isolate, object, index,
505 LookupIterator::OWN_SKIP_INTERCEPTOR);
506 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
507 if (!maybe.IsJust()) return isolate->heap()->exception();
508 RUNTIME_ASSERT(!it.IsFound());
509
510 if (object->IsJSArray()) {
511 Handle<JSArray> array = Handle<JSArray>::cast(object);
512 RUNTIME_ASSERT(!JSArray::WouldChangeReadOnlyLength(array, index));
513 }
514#endif
515
516 Handle<Object> result;
517 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
518 isolate, result,
519 JSObject::SetOwnElementIgnoreAttributes(object, index, value, NONE));
520 return *result;
521}
522
523
524RUNTIME_FUNCTION(Runtime_AppendElement) {
525 HandleScope scope(isolate);
526 RUNTIME_ASSERT(args.length() == 2);
527
528 CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
529 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
530
531 uint32_t index;
532 CHECK(array->length()->ToArrayIndex(&index));
533
534 Handle<Object> result;
535 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
536 isolate, result, JSObject::AddDataElement(array, index, value, NONE));
537 JSObject::ValidateElements(array);
538 return *array;
539}
540
541
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400542RUNTIME_FUNCTION(Runtime_SetProperty) {
543 HandleScope scope(isolate);
544 RUNTIME_ASSERT(args.length() == 4);
545
546 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
547 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
548 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3);
550 LanguageMode language_mode = language_mode_arg;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400551
552 Handle<Object> result;
553 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
554 isolate, result,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555 Runtime::SetObjectProperty(isolate, object, key, value, language_mode));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400556 return *result;
557}
558
559
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560namespace {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400561
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000562// ES6 section 12.5.4.
563Object* DeleteProperty(Isolate* isolate, Handle<Object> object,
564 Handle<Object> key, LanguageMode language_mode) {
565 Handle<JSReceiver> receiver;
566 if (!JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) {
567 THROW_NEW_ERROR_RETURN_FAILURE(
568 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
569 }
570 Maybe<bool> result =
571 Runtime::DeleteObjectProperty(isolate, receiver, key, language_mode);
572 MAYBE_RETURN(result, isolate->heap()->exception());
573 return isolate->heap()->ToBoolean(result.FromJust());
574}
575
576} // namespace
577
578
579RUNTIME_FUNCTION(Runtime_DeleteProperty_Sloppy) {
580 HandleScope scope(isolate);
581 DCHECK_EQ(2, args.length());
582 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400583 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000584 return DeleteProperty(isolate, object, key, SLOPPY);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400585}
586
587
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588RUNTIME_FUNCTION(Runtime_DeleteProperty_Strict) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400589 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000590 DCHECK_EQ(2, args.length());
591 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
592 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
593 return DeleteProperty(isolate, object, key, STRICT);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400594}
595
596
597static Object* HasOwnPropertyImplementation(Isolate* isolate,
598 Handle<JSObject> object,
599 Handle<Name> key) {
600 Maybe<bool> maybe = JSReceiver::HasOwnProperty(object, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000601 if (!maybe.IsJust()) return isolate->heap()->exception();
602 if (maybe.FromJust()) return isolate->heap()->true_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400603 // Handle hidden prototypes. If there's a hidden prototype above this thing
604 // then we have to check it for properties, because they are supposed to
605 // look like they are on this object.
606 PrototypeIterator iter(isolate, object);
607 if (!iter.IsAtEnd() &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000608 PrototypeIterator::GetCurrent<HeapObject>(iter)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400609 ->map()
610 ->is_hidden_prototype()) {
611 // TODO(verwaest): The recursion is not necessary for keys that are array
612 // indices. Removing this.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000613 // Casting to JSObject is fine because JSProxies are never used as
614 // hidden prototypes.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400615 return HasOwnPropertyImplementation(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000616 isolate, PrototypeIterator::GetCurrent<JSObject>(iter), key);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400617 }
618 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
619 return isolate->heap()->false_value();
620}
621
622
623RUNTIME_FUNCTION(Runtime_HasOwnProperty) {
624 HandleScope scope(isolate);
625 DCHECK(args.length() == 2);
626 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0)
627 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
628
629 uint32_t index;
630 const bool key_is_array_index = key->AsArrayIndex(&index);
631
632 // Only JS objects can have properties.
633 if (object->IsJSObject()) {
634 Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
635 // Fast case: either the key is a real named property or it is not
636 // an array index and there are no interceptors or hidden
637 // prototypes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000638 // TODO(jkummerow): Make JSReceiver::HasOwnProperty fast enough to
639 // handle all cases directly (without this custom fast path).
640 Maybe<bool> maybe = Nothing<bool>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400641 if (key_is_array_index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000642 LookupIterator it(js_obj->GetIsolate(), js_obj, index,
643 LookupIterator::HIDDEN);
644 maybe = JSReceiver::HasProperty(&it);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400645 } else {
646 maybe = JSObject::HasRealNamedProperty(js_obj, key);
647 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000648 if (!maybe.IsJust()) return isolate->heap()->exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400649 DCHECK(!isolate->has_pending_exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000650 if (maybe.FromJust()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400651 return isolate->heap()->true_value();
652 }
653 Map* map = js_obj->map();
654 if (!key_is_array_index && !map->has_named_interceptor() &&
655 !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
656 return isolate->heap()->false_value();
657 }
658 // Slow case.
659 return HasOwnPropertyImplementation(isolate, Handle<JSObject>(js_obj),
660 Handle<Name>(key));
661 } else if (object->IsString() && key_is_array_index) {
662 // Well, there is one exception: Handle [] on strings.
663 Handle<String> string = Handle<String>::cast(object);
664 if (index < static_cast<uint32_t>(string->length())) {
665 return isolate->heap()->true_value();
666 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000667 } else if (object->IsJSProxy()) {
668 Maybe<bool> result =
669 JSReceiver::HasOwnProperty(Handle<JSProxy>::cast(object), key);
670 if (!result.IsJust()) return isolate->heap()->exception();
671 return isolate->heap()->ToBoolean(result.FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400672 }
673 return isolate->heap()->false_value();
674}
675
676
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000677// ES6 section 12.9.3, operator in.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400678RUNTIME_FUNCTION(Runtime_HasProperty) {
679 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000680 DCHECK_EQ(2, args.length());
681 CONVERT_ARG_HANDLE_CHECKED(Object, key, 0);
682 CONVERT_ARG_HANDLE_CHECKED(Object, object, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000684 // Check that {object} is actually a receiver.
685 if (!object->IsJSReceiver()) {
686 THROW_NEW_ERROR_RETURN_FAILURE(
687 isolate,
688 NewTypeError(MessageTemplate::kInvalidInOperatorUse, key, object));
689 }
690 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
691
692 // Convert the {key} to a name.
693 Handle<Name> name;
694 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
695 Object::ToName(isolate, key));
696
697 // Lookup the {name} on {receiver}.
698 Maybe<bool> maybe = JSReceiver::HasProperty(receiver, name);
699 if (!maybe.IsJust()) return isolate->heap()->exception();
700 return isolate->heap()->ToBoolean(maybe.FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400701}
702
703
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000704RUNTIME_FUNCTION(Runtime_PropertyIsEnumerable) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400705 HandleScope scope(isolate);
706 DCHECK(args.length() == 2);
707
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000708 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400709 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
710
711 Maybe<PropertyAttributes> maybe =
712 JSReceiver::GetOwnPropertyAttributes(object, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000713 if (!maybe.IsJust()) return isolate->heap()->exception();
714 if (maybe.FromJust() == ABSENT) return isolate->heap()->false_value();
715 return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400716}
717
718
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000719// Returns either a FixedArray or, if the given object has an enum cache that
720// contains all enumerable properties of the object and its prototypes have
721// none, the map of the object. This is used to speed up the check for
722// deletions during a for-in.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400723RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) {
724 SealHandleScope shs(isolate);
725 DCHECK(args.length() == 1);
726
727 CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
728
729 if (raw_object->IsSimpleEnum()) return raw_object->map();
730
731 HandleScope scope(isolate);
732 Handle<JSReceiver> object(raw_object);
733 Handle<FixedArray> content;
734 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 isolate, content, JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS,
736 ENUMERABLE_STRINGS));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400737
738 // Test again, since cache may have been built by preceding call.
739 if (object->IsSimpleEnum()) return object->map();
740
741 return *content;
742}
743
744
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000745RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400746 HandleScope scope(isolate);
747 DCHECK(args.length() == 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000748 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400749 CONVERT_SMI_ARG_CHECKED(filter_value, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000750 PropertyFilter filter = static_cast<PropertyFilter>(filter_value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400751
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000752 Handle<FixedArray> keys;
753 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
754 isolate, keys, JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY, filter,
755 CONVERT_TO_STRING));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400756
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757 return *isolate->factory()->NewJSArrayWithElements(keys);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400758}
759
760
761// Return information on whether an object has a named or indexed interceptor.
762// args[0]: object
763RUNTIME_FUNCTION(Runtime_GetInterceptorInfo) {
764 HandleScope scope(isolate);
765 DCHECK(args.length() == 1);
766 if (!args[0]->IsJSObject()) {
767 return Smi::FromInt(0);
768 }
769 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
770
771 int result = 0;
772 if (obj->HasNamedInterceptor()) result |= 2;
773 if (obj->HasIndexedInterceptor()) result |= 1;
774
775 return Smi::FromInt(result);
776}
777
778
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400779RUNTIME_FUNCTION(Runtime_ToFastProperties) {
780 HandleScope scope(isolate);
781 DCHECK(args.length() == 1);
782 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000783 if (object->IsJSObject() && !object->IsJSGlobalObject()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400784 JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0,
785 "RuntimeToFastProperties");
786 }
787 return *object;
788}
789
790
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400791RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) {
792 HandleScope scope(isolate);
793 DCHECK(args.length() == 0);
794 return *isolate->factory()->NewHeapNumber(0);
795}
796
797
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400798RUNTIME_FUNCTION(Runtime_NewObject) {
799 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000800 DCHECK_EQ(2, args.length());
801 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
802 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, new_target, 1);
803 Handle<JSObject> result;
804 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
805 JSObject::New(target, new_target));
806 return *result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400807}
808
809
810RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) {
811 HandleScope scope(isolate);
812 DCHECK(args.length() == 1);
813
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000814 CONVERT_ARG_HANDLE_CHECKED(Map, initial_map, 0);
815 initial_map->CompleteInobjectSlackTracking();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400816
817 return isolate->heap()->undefined_value();
818}
819
820
821RUNTIME_FUNCTION(Runtime_GlobalProxy) {
822 SealHandleScope shs(isolate);
823 DCHECK(args.length() == 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000824 CONVERT_ARG_CHECKED(JSFunction, function, 0);
825 return function->context()->global_proxy();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400826}
827
828
829RUNTIME_FUNCTION(Runtime_LookupAccessor) {
830 HandleScope scope(isolate);
831 DCHECK(args.length() == 3);
832 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
833 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
834 CONVERT_SMI_ARG_CHECKED(flag, 2);
835 AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
836 if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
837 Handle<Object> result;
838 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
839 isolate, result,
840 JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component));
841 return *result;
842}
843
844
845RUNTIME_FUNCTION(Runtime_LoadMutableDouble) {
846 HandleScope scope(isolate);
847 DCHECK(args.length() == 2);
848 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
849 CONVERT_ARG_HANDLE_CHECKED(Smi, index, 1);
850 RUNTIME_ASSERT((index->value() & 1) == 1);
851 FieldIndex field_index =
852 FieldIndex::ForLoadByFieldIndex(object->map(), index->value());
853 if (field_index.is_inobject()) {
854 RUNTIME_ASSERT(field_index.property_index() <
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000855 object->map()->GetInObjectProperties());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400856 } else {
857 RUNTIME_ASSERT(field_index.outobject_array_index() <
858 object->properties()->length());
859 }
860 return *JSObject::FastPropertyAt(object, Representation::Double(),
861 field_index);
862}
863
864
865RUNTIME_FUNCTION(Runtime_TryMigrateInstance) {
866 HandleScope scope(isolate);
867 DCHECK(args.length() == 1);
868 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
869 if (!object->IsJSObject()) return Smi::FromInt(0);
870 Handle<JSObject> js_object = Handle<JSObject>::cast(object);
871 if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
872 // This call must not cause lazy deopts, because it's called from deferred
873 // code where we can't handle lazy deopts for lack of a suitable bailout
874 // ID. So we just try migration and signal failure if necessary,
875 // which will also trigger a deopt.
876 if (!JSObject::TryMigrateInstance(js_object)) return Smi::FromInt(0);
877 return *object;
878}
879
880
881RUNTIME_FUNCTION(Runtime_IsJSGlobalProxy) {
882 SealHandleScope shs(isolate);
883 DCHECK(args.length() == 1);
884 CONVERT_ARG_CHECKED(Object, obj, 0);
885 return isolate->heap()->ToBoolean(obj->IsJSGlobalProxy());
886}
887
888
889static bool IsValidAccessor(Handle<Object> obj) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000890 return obj->IsUndefined() || obj->IsCallable() || obj->IsNull();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400891}
892
893
894// Implements part of 8.12.9 DefineOwnProperty.
895// There are 3 cases that lead here:
896// Step 4b - define a new accessor property.
897// Steps 9c & 12 - replace an existing data property with an accessor property.
898// Step 12 - update an existing accessor property with an accessor or generic
899// descriptor.
900RUNTIME_FUNCTION(Runtime_DefineAccessorPropertyUnchecked) {
901 HandleScope scope(isolate);
902 DCHECK(args.length() == 5);
903 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
904 RUNTIME_ASSERT(!obj->IsNull());
905 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
906 CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
907 RUNTIME_ASSERT(IsValidAccessor(getter));
908 CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
909 RUNTIME_ASSERT(IsValidAccessor(setter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000910 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 4);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400911
912 RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000913 isolate, JSObject::DefineAccessor(obj, name, getter, setter, attrs));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400914 return isolate->heap()->undefined_value();
915}
916
917
918// Implements part of 8.12.9 DefineOwnProperty.
919// There are 3 cases that lead here:
920// Step 4a - define a new data property.
921// Steps 9b & 12 - replace an existing accessor property with a data property.
922// Step 12 - update an existing data property with a data or generic
923// descriptor.
924RUNTIME_FUNCTION(Runtime_DefineDataPropertyUnchecked) {
925 HandleScope scope(isolate);
926 DCHECK(args.length() == 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000927 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400928 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
930 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400931
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932 LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, name,
933 LookupIterator::OWN);
934 if (it.state() == LookupIterator::ACCESS_CHECK && !it.HasAccess()) {
935 return isolate->heap()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400936 }
937
938 Handle<Object> result;
939 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000940 isolate, result, JSObject::DefineOwnPropertyIgnoreAttributes(
941 &it, value, attrs, JSObject::DONT_FORCE_FIELD));
942
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400943 return *result;
944}
945
946
947// Return property without being observable by accessors or interceptors.
948RUNTIME_FUNCTION(Runtime_GetDataProperty) {
949 HandleScope scope(isolate);
950 DCHECK(args.length() == 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
952 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
953 return *JSReceiver::GetDataProperty(object, name);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400954}
955
956
957RUNTIME_FUNCTION(Runtime_HasFastPackedElements) {
958 SealHandleScope shs(isolate);
959 DCHECK(args.length() == 1);
960 CONVERT_ARG_CHECKED(HeapObject, obj, 0);
961 return isolate->heap()->ToBoolean(
962 IsFastPackedElementsKind(obj->map()->elements_kind()));
963}
964
965
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000966RUNTIME_FUNCTION(Runtime_ValueOf) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400967 SealHandleScope shs(isolate);
968 DCHECK(args.length() == 1);
969 CONVERT_ARG_CHECKED(Object, obj, 0);
970 if (!obj->IsJSValue()) return obj;
971 return JSValue::cast(obj)->value();
972}
973
974
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000975RUNTIME_FUNCTION(Runtime_SetValueOf) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400976 SealHandleScope shs(isolate);
977 DCHECK(args.length() == 2);
978 CONVERT_ARG_CHECKED(Object, obj, 0);
979 CONVERT_ARG_CHECKED(Object, value, 1);
980 if (!obj->IsJSValue()) return value;
981 JSValue::cast(obj)->set_value(value);
982 return value;
983}
984
985
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000986RUNTIME_FUNCTION(Runtime_JSValueGetValue) {
987 SealHandleScope shs(isolate);
988 DCHECK(args.length() == 1);
989 CONVERT_ARG_CHECKED(JSValue, obj, 0);
990 return JSValue::cast(obj)->value();
991}
992
993
994RUNTIME_FUNCTION(Runtime_ObjectEquals) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400995 SealHandleScope shs(isolate);
996 DCHECK(args.length() == 2);
997 CONVERT_ARG_CHECKED(Object, obj1, 0);
998 CONVERT_ARG_CHECKED(Object, obj2, 1);
999 return isolate->heap()->ToBoolean(obj1 == obj2);
1000}
1001
1002
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001003RUNTIME_FUNCTION(Runtime_IsJSReceiver) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001004 SealHandleScope shs(isolate);
1005 DCHECK(args.length() == 1);
1006 CONVERT_ARG_CHECKED(Object, obj, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001007 return isolate->heap()->ToBoolean(obj->IsJSReceiver());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001008}
1009
1010
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011RUNTIME_FUNCTION(Runtime_IsStrong) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001012 SealHandleScope shs(isolate);
1013 DCHECK(args.length() == 1);
1014 CONVERT_ARG_CHECKED(Object, obj, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001015 return isolate->heap()->ToBoolean(obj->IsJSReceiver() &&
1016 JSReceiver::cast(obj)->map()->is_strong());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001017}
1018
1019
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001020RUNTIME_FUNCTION(Runtime_ClassOf) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001021 SealHandleScope shs(isolate);
1022 DCHECK(args.length() == 1);
1023 CONVERT_ARG_CHECKED(Object, obj, 0);
1024 if (!obj->IsJSReceiver()) return isolate->heap()->null_value();
1025 return JSReceiver::cast(obj)->class_name();
1026}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001027
1028
1029RUNTIME_FUNCTION(Runtime_DefineGetterPropertyUnchecked) {
1030 HandleScope scope(isolate);
1031 DCHECK(args.length() == 4);
1032 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1033 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1034 CONVERT_ARG_HANDLE_CHECKED(JSFunction, getter, 2);
1035 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1036
1037 RETURN_FAILURE_ON_EXCEPTION(
1038 isolate,
1039 JSObject::DefineAccessor(object, name, getter,
1040 isolate->factory()->null_value(), attrs));
1041 return isolate->heap()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001042}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043
1044
1045RUNTIME_FUNCTION(Runtime_DefineSetterPropertyUnchecked) {
1046 HandleScope scope(isolate);
1047 DCHECK(args.length() == 4);
1048 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1049 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1050 CONVERT_ARG_HANDLE_CHECKED(JSFunction, setter, 2);
1051 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3);
1052
1053 RETURN_FAILURE_ON_EXCEPTION(
1054 isolate,
1055 JSObject::DefineAccessor(object, name, isolate->factory()->null_value(),
1056 setter, attrs));
1057 return isolate->heap()->undefined_value();
1058}
1059
1060
1061RUNTIME_FUNCTION(Runtime_ToObject) {
1062 HandleScope scope(isolate);
1063 DCHECK_EQ(1, args.length());
1064 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1065 Handle<JSReceiver> receiver;
1066 if (JSReceiver::ToObject(isolate, object).ToHandle(&receiver)) {
1067 return *receiver;
1068 }
1069 THROW_NEW_ERROR_RETURN_FAILURE(
1070 isolate, NewTypeError(MessageTemplate::kUndefinedOrNullToObject));
1071}
1072
1073
1074RUNTIME_FUNCTION(Runtime_ToPrimitive) {
1075 HandleScope scope(isolate);
1076 DCHECK_EQ(1, args.length());
1077 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1078 Handle<Object> result;
1079 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1080 Object::ToPrimitive(input));
1081 return *result;
1082}
1083
1084
1085RUNTIME_FUNCTION(Runtime_ToPrimitive_Number) {
1086 HandleScope scope(isolate);
1087 DCHECK_EQ(1, args.length());
1088 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1089 Handle<Object> result;
1090 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1091 isolate, result, Object::ToPrimitive(input, ToPrimitiveHint::kNumber));
1092 return *result;
1093}
1094
1095
1096RUNTIME_FUNCTION(Runtime_ToPrimitive_String) {
1097 HandleScope scope(isolate);
1098 DCHECK_EQ(1, args.length());
1099 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1100 Handle<Object> result;
1101 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1102 isolate, result, Object::ToPrimitive(input, ToPrimitiveHint::kString));
1103 return *result;
1104}
1105
1106
1107RUNTIME_FUNCTION(Runtime_ToNumber) {
1108 HandleScope scope(isolate);
1109 DCHECK_EQ(1, args.length());
1110 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1111 Handle<Object> result;
1112 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::ToNumber(input));
1113 return *result;
1114}
1115
1116
1117RUNTIME_FUNCTION(Runtime_ToInteger) {
1118 HandleScope scope(isolate);
1119 DCHECK_EQ(1, args.length());
1120 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1121 Handle<Object> result;
1122 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1123 Object::ToInteger(isolate, input));
1124 return *result;
1125}
1126
1127
1128RUNTIME_FUNCTION(Runtime_ToLength) {
1129 HandleScope scope(isolate);
1130 DCHECK_EQ(1, args.length());
1131 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1132 Handle<Object> result;
1133 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1134 Object::ToLength(isolate, input));
1135 return *result;
1136}
1137
1138
1139RUNTIME_FUNCTION(Runtime_ToString) {
1140 HandleScope scope(isolate);
1141 DCHECK_EQ(1, args.length());
1142 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1143 Handle<Object> result;
1144 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1145 Object::ToString(isolate, input));
1146 return *result;
1147}
1148
1149
1150RUNTIME_FUNCTION(Runtime_ToName) {
1151 HandleScope scope(isolate);
1152 DCHECK_EQ(1, args.length());
1153 CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
1154 Handle<Object> result;
1155 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1156 Object::ToName(isolate, input));
1157 return *result;
1158}
1159
1160
1161RUNTIME_FUNCTION(Runtime_Equals) {
1162 HandleScope scope(isolate);
1163 DCHECK_EQ(2, args.length());
1164 CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
1165 CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
1166 Maybe<bool> result = Object::Equals(x, y);
1167 if (!result.IsJust()) return isolate->heap()->exception();
1168 // TODO(bmeurer): Change this at some point to return true/false instead.
1169 return Smi::FromInt(result.FromJust() ? EQUAL : NOT_EQUAL);
1170}
1171
1172
1173RUNTIME_FUNCTION(Runtime_StrictEquals) {
1174 SealHandleScope scope(isolate);
1175 DCHECK_EQ(2, args.length());
1176 CONVERT_ARG_CHECKED(Object, x, 0);
1177 CONVERT_ARG_CHECKED(Object, y, 1);
1178 // TODO(bmeurer): Change this at some point to return true/false instead.
1179 return Smi::FromInt(x->StrictEquals(y) ? EQUAL : NOT_EQUAL);
1180}
1181
1182
1183// TODO(bmeurer): Kill this special wrapper and use TF compatible LessThan,
1184// GreaterThan, etc. which return true or false.
1185RUNTIME_FUNCTION(Runtime_Compare) {
1186 HandleScope scope(isolate);
1187 DCHECK_EQ(3, args.length());
1188 CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
1189 CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
1190 CONVERT_ARG_HANDLE_CHECKED(Object, ncr, 2);
1191 Maybe<ComparisonResult> result = Object::Compare(x, y);
1192 if (result.IsJust()) {
1193 switch (result.FromJust()) {
1194 case ComparisonResult::kLessThan:
1195 return Smi::FromInt(LESS);
1196 case ComparisonResult::kEqual:
1197 return Smi::FromInt(EQUAL);
1198 case ComparisonResult::kGreaterThan:
1199 return Smi::FromInt(GREATER);
1200 case ComparisonResult::kUndefined:
1201 return *ncr;
1202 }
1203 UNREACHABLE();
1204 }
1205 return isolate->heap()->exception();
1206}
1207
1208
1209// TODO(bmeurer): Kill this special wrapper and use TF compatible LessThan,
1210// GreaterThan, etc. which return true or false.
1211RUNTIME_FUNCTION(Runtime_Compare_Strong) {
1212 HandleScope scope(isolate);
1213 DCHECK_EQ(3, args.length());
1214 CONVERT_ARG_HANDLE_CHECKED(Object, x, 0);
1215 CONVERT_ARG_HANDLE_CHECKED(Object, y, 1);
1216 CONVERT_ARG_HANDLE_CHECKED(Object, ncr, 2);
1217 Maybe<ComparisonResult> result = Object::Compare(x, y, Strength::STRONG);
1218 if (result.IsJust()) {
1219 switch (result.FromJust()) {
1220 case ComparisonResult::kLessThan:
1221 return Smi::FromInt(LESS);
1222 case ComparisonResult::kEqual:
1223 return Smi::FromInt(EQUAL);
1224 case ComparisonResult::kGreaterThan:
1225 return Smi::FromInt(GREATER);
1226 case ComparisonResult::kUndefined:
1227 return *ncr;
1228 }
1229 UNREACHABLE();
1230 }
1231 return isolate->heap()->exception();
1232}
1233
1234
1235RUNTIME_FUNCTION(Runtime_InstanceOf) {
1236 // ECMA-262, section 11.8.6, page 54.
1237 HandleScope shs(isolate);
1238 DCHECK_EQ(2, args.length());
1239 DCHECK(args.length() == 2);
1240 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1241 CONVERT_ARG_HANDLE_CHECKED(Object, callable, 1);
1242 // {callable} must have a [[Call]] internal method.
1243 if (!callable->IsCallable()) {
1244 THROW_NEW_ERROR_RETURN_FAILURE(
1245 isolate,
1246 NewTypeError(MessageTemplate::kInstanceofFunctionExpected, callable));
1247 }
1248 // If {object} is not a receiver, return false.
1249 if (!object->IsJSReceiver()) {
1250 return isolate->heap()->false_value();
1251 }
1252 // Check if {callable} is bound, if so, get [[BoundTargetFunction]] from it
1253 // and use that instead of {callable}.
1254 while (callable->IsJSBoundFunction()) {
1255 callable =
1256 handle(Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
1257 isolate);
1258 }
1259 DCHECK(callable->IsCallable());
1260 // Get the "prototype" of {callable}; raise an error if it's not a receiver.
1261 Handle<Object> prototype;
1262 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1263 isolate, prototype,
1264 Object::GetProperty(callable, isolate->factory()->prototype_string()));
1265 if (!prototype->IsJSReceiver()) {
1266 THROW_NEW_ERROR_RETURN_FAILURE(
1267 isolate,
1268 NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype));
1269 }
1270 // Return whether or not {prototype} is in the prototype chain of {object}.
1271 Maybe<bool> result = Object::HasInPrototypeChain(isolate, object, prototype);
1272 MAYBE_RETURN(result, isolate->heap()->exception());
1273 return isolate->heap()->ToBoolean(result.FromJust());
1274}
1275
1276
1277RUNTIME_FUNCTION(Runtime_HasInPrototypeChain) {
1278 HandleScope scope(isolate);
1279 DCHECK_EQ(2, args.length());
1280 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
1281 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1282 Maybe<bool> result = Object::HasInPrototypeChain(isolate, object, prototype);
1283 MAYBE_RETURN(result, isolate->heap()->exception());
1284 return isolate->heap()->ToBoolean(result.FromJust());
1285}
1286
1287
1288// ES6 section 7.4.7 CreateIterResultObject ( value, done )
1289RUNTIME_FUNCTION(Runtime_CreateIterResultObject) {
1290 HandleScope scope(isolate);
1291 DCHECK_EQ(2, args.length());
1292 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
1293 CONVERT_ARG_HANDLE_CHECKED(Object, done, 1);
1294 return *isolate->factory()->NewJSIteratorResult(value, done);
1295}
1296
1297
1298RUNTIME_FUNCTION(Runtime_IsAccessCheckNeeded) {
1299 SealHandleScope shs(isolate);
1300 DCHECK_EQ(1, args.length());
1301 CONVERT_ARG_CHECKED(Object, object, 0);
1302 return isolate->heap()->ToBoolean(object->IsAccessCheckNeeded());
1303}
1304
1305
1306RUNTIME_FUNCTION(Runtime_ObjectDefineProperty) {
1307 HandleScope scope(isolate);
1308 DCHECK(args.length() == 3);
1309 CONVERT_ARG_HANDLE_CHECKED(Object, o, 0);
1310 CONVERT_ARG_HANDLE_CHECKED(Object, name, 1);
1311 CONVERT_ARG_HANDLE_CHECKED(Object, attributes, 2);
1312 return JSReceiver::DefineProperty(isolate, o, name, attributes);
1313}
1314
1315
1316RUNTIME_FUNCTION(Runtime_ObjectDefineProperties) {
1317 HandleScope scope(isolate);
1318 DCHECK(args.length() == 2);
1319 CONVERT_ARG_HANDLE_CHECKED(Object, o, 0);
1320 CONVERT_ARG_HANDLE_CHECKED(Object, properties, 1);
1321 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1322 isolate, o, JSReceiver::DefineProperties(isolate, o, properties));
1323 return *o;
1324}
1325
1326} // namespace internal
1327} // namespace v8