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 3// found in the LICENSE file. 4 5#include "src/runtime/runtime-utils.h" 6 7#include "src/arguments.h" 8#include "src/bootstrapper.h" 9#include "src/debug/debug.h" 10#include "src/isolate-inl.h" 11#include "src/messages.h" 12#include "src/property-descriptor.h" 13#include "src/runtime/runtime.h" 14 15namespace v8 { 16namespace internal { 17 18 19MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate, 20 Handle<Object> object, 21 Handle<Object> key, 22 LanguageMode language_mode) { 23 if (object->IsUndefined() || object->IsNull()) { 24 THROW_NEW_ERROR( 25 isolate, 26 NewTypeError(MessageTemplate::kNonObjectPropertyLoad, key, object), 27 Object); 28 } 29 30 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 } 113 } 114 115 // Fall back to GetObjectProperty. 116 return Runtime::GetObjectProperty(isolate, receiver_obj, key_obj, 117 language_mode); 118} 119 120 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); 131} 132 133 134MaybeHandle<Object> Runtime::SetObjectProperty(Isolate* isolate, 135 Handle<Object> object, 136 Handle<Object> key, 137 Handle<Object> value, 138 LanguageMode language_mode) { 139 if (object->IsUndefined() || object->IsNull()) { 140 THROW_NEW_ERROR( 141 isolate, 142 NewTypeError(MessageTemplate::kNonObjectPropertyStore, key, object), 143 Object); 144 } 145 146 // Check if the given key is an array index. 147 bool success = false; 148 LookupIterator it = 149 LookupIterator::PropertyOrElement(isolate, object, key, &success); 150 if (!success) return MaybeHandle<Object>(); 151 152 MAYBE_RETURN_NULL(Object::SetProperty(&it, value, language_mode, 153 Object::MAY_BE_STORE_FROM_KEYED)); 154 return value; 155} 156 157 158RUNTIME_FUNCTION(Runtime_GetPrototype) { 159 HandleScope scope(isolate); 160 DCHECK(args.length() == 1); 161 CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0); 162 Handle<Object> prototype; 163 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype, 164 Object::GetPrototype(isolate, obj)); 165 return *prototype; 166} 167 168 169RUNTIME_FUNCTION(Runtime_InternalSetPrototype) { 170 HandleScope scope(isolate); 171 DCHECK(args.length() == 2); 172 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0); 173 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); 174 MAYBE_RETURN( 175 JSReceiver::SetPrototype(obj, prototype, false, Object::THROW_ON_ERROR), 176 isolate->heap()->exception()); 177 return *obj; 178} 179 180 181RUNTIME_FUNCTION(Runtime_SetPrototype) { 182 HandleScope scope(isolate); 183 DCHECK(args.length() == 2); 184 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0); 185 CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1); 186 MAYBE_RETURN( 187 JSReceiver::SetPrototype(obj, prototype, true, Object::THROW_ON_ERROR), 188 isolate->heap()->exception()); 189 return *obj; 190} 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 212 // Get attributes. 213 LookupIterator it = LookupIterator::PropertyOrElement(isolate, obj, name, 214 LookupIterator::HIDDEN); 215 Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(&it); 216 217 if (!maybe.IsJust()) return MaybeHandle<Object>(); 218 PropertyAttributes attrs = maybe.FromJust(); 219 if (attrs == ABSENT) return factory->undefined_value(); 220 221 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)); 225 226 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()); 233 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 { 238 Handle<Object> value; 239 ASSIGN_RETURN_ON_EXCEPTION(isolate, value, Object::GetProperty(&it), 240 Object); 241 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] 256// TODO(jkummerow): Deprecated. Remove all callers and delete. 257RUNTIME_FUNCTION(Runtime_GetOwnProperty_Legacy) { 258 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 269// ES6 19.1.2.6 270RUNTIME_FUNCTION(Runtime_GetOwnProperty) { 271 HandleScope scope(isolate); 272 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)); 282 283 // 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); 291} 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 309RUNTIME_FUNCTION(Runtime_LoadGlobalViaContext) { 310 HandleScope scope(isolate); 311 DCHECK_EQ(1, args.length()); 312 CONVERT_SMI_ARG_CHECKED(slot, 0); 313 314 // 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 } 338 339 Handle<Object> result; 340 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, Object::GetProperty(&it)); 341 return *result; 342} 343 344 345namespace { 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) { 384 HandleScope scope(isolate); 385 DCHECK_EQ(2, args.length()); 386 CONVERT_SMI_ARG_CHECKED(slot, 0); 387 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); 388 389 return StoreGlobalViaContext(isolate, slot, value, SLOPPY); 390} 391 392 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); 400} 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); 409 410 Handle<Object> result; 411 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 412 isolate, result, 413 Runtime::GetObjectProperty(isolate, object, key, SLOPPY)); 414 return *result; 415} 416 417 418RUNTIME_FUNCTION(Runtime_GetPropertyStrong) { 419 HandleScope scope(isolate); 420 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; 430} 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 441 Handle<Object> result; 442 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 443 isolate, result, 444 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)); 460 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); 469 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); 470 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); 471 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); 472 473#ifdef DEBUG 474 uint32_t index = 0; 475 DCHECK(!name->ToArrayIndex(&index)); 476 LookupIterator it(object, name, LookupIterator::OWN_SKIP_INTERCEPTOR); 477 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); 478 if (!maybe.IsJust()) return isolate->heap()->exception(); 479 RUNTIME_ASSERT(!it.IsFound()); 480#endif 481 482 Handle<Object> result; 483 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 484 isolate, result, 485 JSObject::SetOwnPropertyIgnoreAttributes(object, name, value, attrs)); 486 return *result; 487} 488 489 490// 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 542RUNTIME_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); 549 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode_arg, 3); 550 LanguageMode language_mode = language_mode_arg; 551 552 Handle<Object> result; 553 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 554 isolate, result, 555 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); 556 return *result; 557} 558 559 560namespace { 561 562// 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); 583 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); 584 return DeleteProperty(isolate, object, key, SLOPPY); 585} 586 587 588RUNTIME_FUNCTION(Runtime_DeleteProperty_Strict) { 589 HandleScope scope(isolate); 590 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); 594} 595 596 597static Object* HasOwnPropertyImplementation(Isolate* isolate, 598 Handle<JSObject> object, 599 Handle<Name> key) { 600 Maybe<bool> maybe = JSReceiver::HasOwnProperty(object, key); 601 if (!maybe.IsJust()) return isolate->heap()->exception(); 602 if (maybe.FromJust()) return isolate->heap()->true_value(); 603 // 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() && 608 PrototypeIterator::GetCurrent<HeapObject>(iter) 609 ->map() 610 ->is_hidden_prototype()) { 611 // TODO(verwaest): The recursion is not necessary for keys that are array 612 // indices. Removing this. 613 // Casting to JSObject is fine because JSProxies are never used as 614 // hidden prototypes. 615 return HasOwnPropertyImplementation( 616 isolate, PrototypeIterator::GetCurrent<JSObject>(iter), key); 617 } 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. 638 // TODO(jkummerow): Make JSReceiver::HasOwnProperty fast enough to 639 // handle all cases directly (without this custom fast path). 640 Maybe<bool> maybe = Nothing<bool>(); 641 if (key_is_array_index) { 642 LookupIterator it(js_obj->GetIsolate(), js_obj, index, 643 LookupIterator::HIDDEN); 644 maybe = JSReceiver::HasProperty(&it); 645 } else { 646 maybe = JSObject::HasRealNamedProperty(js_obj, key); 647 } 648 if (!maybe.IsJust()) return isolate->heap()->exception(); 649 DCHECK(!isolate->has_pending_exception()); 650 if (maybe.FromJust()) { 651 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 } 667 } 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()); 672 } 673 return isolate->heap()->false_value(); 674} 675 676 677// ES6 section 12.9.3, operator in. 678RUNTIME_FUNCTION(Runtime_HasProperty) { 679 HandleScope scope(isolate); 680 DCHECK_EQ(2, args.length()); 681 CONVERT_ARG_HANDLE_CHECKED(Object, key, 0); 682 CONVERT_ARG_HANDLE_CHECKED(Object, object, 1); 683 684 // 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()); 701} 702 703 704RUNTIME_FUNCTION(Runtime_PropertyIsEnumerable) { 705 HandleScope scope(isolate); 706 DCHECK(args.length() == 2); 707 708 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); 709 CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); 710 711 Maybe<PropertyAttributes> maybe = 712 JSReceiver::GetOwnPropertyAttributes(object, key); 713 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); 716} 717 718 719// 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. 723RUNTIME_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( 735 isolate, content, JSReceiver::GetKeys(object, JSReceiver::INCLUDE_PROTOS, 736 ENUMERABLE_STRINGS)); 737 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 745RUNTIME_FUNCTION(Runtime_GetOwnPropertyKeys) { 746 HandleScope scope(isolate); 747 DCHECK(args.length() == 2); 748 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); 749 CONVERT_SMI_ARG_CHECKED(filter_value, 1); 750 PropertyFilter filter = static_cast<PropertyFilter>(filter_value); 751 752 Handle<FixedArray> keys; 753 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 754 isolate, keys, JSReceiver::GetKeys(object, JSReceiver::OWN_ONLY, filter, 755 CONVERT_TO_STRING)); 756 757 return *isolate->factory()->NewJSArrayWithElements(keys); 758} 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 779RUNTIME_FUNCTION(Runtime_ToFastProperties) { 780 HandleScope scope(isolate); 781 DCHECK(args.length() == 1); 782 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); 783 if (object->IsJSObject() && !object->IsJSGlobalObject()) { 784 JSObject::MigrateSlowToFast(Handle<JSObject>::cast(object), 0, 785 "RuntimeToFastProperties"); 786 } 787 return *object; 788} 789 790 791RUNTIME_FUNCTION(Runtime_AllocateHeapNumber) { 792 HandleScope scope(isolate); 793 DCHECK(args.length() == 0); 794 return *isolate->factory()->NewHeapNumber(0); 795} 796 797 798RUNTIME_FUNCTION(Runtime_NewObject) { 799 HandleScope scope(isolate); 800 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; 807} 808 809 810RUNTIME_FUNCTION(Runtime_FinalizeInstanceSize) { 811 HandleScope scope(isolate); 812 DCHECK(args.length() == 1); 813 814 CONVERT_ARG_HANDLE_CHECKED(Map, initial_map, 0); 815 initial_map->CompleteInobjectSlackTracking(); 816 817 return isolate->heap()->undefined_value(); 818} 819 820 821RUNTIME_FUNCTION(Runtime_GlobalProxy) { 822 SealHandleScope shs(isolate); 823 DCHECK(args.length() == 1); 824 CONVERT_ARG_CHECKED(JSFunction, function, 0); 825 return function->context()->global_proxy(); 826} 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() < 855 object->map()->GetInObjectProperties()); 856 } 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) { 890 return obj->IsUndefined() || obj->IsCallable() || obj->IsNull(); 891} 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)); 910 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 4); 911 912 RETURN_FAILURE_ON_EXCEPTION( 913 isolate, JSObject::DefineAccessor(obj, name, getter, setter, attrs)); 914 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); 927 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); 928 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); 929 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); 930 CONVERT_PROPERTY_ATTRIBUTES_CHECKED(attrs, 3); 931 932 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(); 936 } 937 938 Handle<Object> result; 939 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 940 isolate, result, JSObject::DefineOwnPropertyIgnoreAttributes( 941 &it, value, attrs, JSObject::DONT_FORCE_FIELD)); 942 943 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); 951 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0); 952 CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); 953 return *JSReceiver::GetDataProperty(object, name); 954} 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 966RUNTIME_FUNCTION(Runtime_ValueOf) { 967 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 975RUNTIME_FUNCTION(Runtime_SetValueOf) { 976 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 986RUNTIME_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) { 995 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 1003RUNTIME_FUNCTION(Runtime_IsJSReceiver) { 1004 SealHandleScope shs(isolate); 1005 DCHECK(args.length() == 1); 1006 CONVERT_ARG_CHECKED(Object, obj, 0); 1007 return isolate->heap()->ToBoolean(obj->IsJSReceiver()); 1008} 1009 1010 1011RUNTIME_FUNCTION(Runtime_IsStrong) { 1012 SealHandleScope shs(isolate); 1013 DCHECK(args.length() == 1); 1014 CONVERT_ARG_CHECKED(Object, obj, 0); 1015 return isolate->heap()->ToBoolean(obj->IsJSReceiver() && 1016 JSReceiver::cast(obj)->map()->is_strong()); 1017} 1018 1019 1020RUNTIME_FUNCTION(Runtime_ClassOf) { 1021 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} 1027 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(); 1042} 1043 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 1328