Home | History | Annotate | Download | only in builtins
      1 // Copyright 2016 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/builtins/builtins-object.h"
      6 #include "src/builtins/builtins-utils.h"
      7 #include "src/builtins/builtins.h"
      8 #include "src/code-factory.h"
      9 #include "src/code-stub-assembler.h"
     10 #include "src/counters.h"
     11 #include "src/keys.h"
     12 #include "src/lookup.h"
     13 #include "src/objects-inl.h"
     14 #include "src/property-descriptor.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 
     19 typedef compiler::Node Node;
     20 
     21 std::tuple<Node*, Node*, Node*> ObjectBuiltinsAssembler::EmitForInPrepare(
     22     Node* object, Node* context, Label* call_runtime,
     23     Label* nothing_to_iterate) {
     24   Label use_cache(this);
     25   CSA_ASSERT(this, IsJSReceiver(object));
     26 
     27   CheckEnumCache(object, &use_cache, call_runtime);
     28   Bind(&use_cache);
     29   Node* map = LoadMap(object);
     30   Node* enum_length = EnumLength(map);
     31   GotoIf(WordEqual(enum_length, SmiConstant(0)), nothing_to_iterate);
     32   Node* descriptors = LoadMapDescriptors(map);
     33   Node* cache_offset =
     34       LoadObjectField(descriptors, DescriptorArray::kEnumCacheOffset);
     35   Node* enum_cache = LoadObjectField(
     36       cache_offset, DescriptorArray::kEnumCacheBridgeCacheOffset);
     37 
     38   return std::make_tuple(map, enum_cache, enum_length);
     39 }
     40 // -----------------------------------------------------------------------------
     41 // ES6 section 19.1 Object Objects
     42 
     43 TF_BUILTIN(ObjectHasOwnProperty, ObjectBuiltinsAssembler) {
     44   Node* object = Parameter(0);
     45   Node* key = Parameter(1);
     46   Node* context = Parameter(4);
     47 
     48   Label call_runtime(this), return_true(this), return_false(this);
     49 
     50   // Smi receivers do not have own properties.
     51   Label if_objectisnotsmi(this);
     52   Branch(TaggedIsSmi(object), &return_false, &if_objectisnotsmi);
     53   Bind(&if_objectisnotsmi);
     54 
     55   Node* map = LoadMap(object);
     56   Node* instance_type = LoadMapInstanceType(map);
     57 
     58   {
     59     Variable var_index(this, MachineType::PointerRepresentation());
     60     Variable var_unique(this, MachineRepresentation::kTagged);
     61 
     62     Label keyisindex(this), if_iskeyunique(this);
     63     TryToName(key, &keyisindex, &var_index, &if_iskeyunique, &var_unique,
     64               &call_runtime);
     65 
     66     Bind(&if_iskeyunique);
     67     TryHasOwnProperty(object, map, instance_type, var_unique.value(),
     68                       &return_true, &return_false, &call_runtime);
     69 
     70     Bind(&keyisindex);
     71     // Handle negative keys in the runtime.
     72     GotoIf(IntPtrLessThan(var_index.value(), IntPtrConstant(0)), &call_runtime);
     73     TryLookupElement(object, map, instance_type, var_index.value(),
     74                      &return_true, &return_false, &call_runtime);
     75   }
     76   Bind(&return_true);
     77   Return(BooleanConstant(true));
     78 
     79   Bind(&return_false);
     80   Return(BooleanConstant(false));
     81 
     82   Bind(&call_runtime);
     83   Return(CallRuntime(Runtime::kObjectHasOwnProperty, context, object, key));
     84 }
     85 
     86 // ES6 19.1.2.1 Object.assign
     87 BUILTIN(ObjectAssign) {
     88   HandleScope scope(isolate);
     89   Handle<Object> target = args.atOrUndefined(isolate, 1);
     90 
     91   // 1. Let to be ? ToObject(target).
     92   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
     93                                      Object::ToObject(isolate, target));
     94   Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
     95   // 2. If only one argument was passed, return to.
     96   if (args.length() == 2) return *to;
     97   // 3. Let sources be the List of argument values starting with the
     98   //    second argument.
     99   // 4. For each element nextSource of sources, in ascending index order,
    100   for (int i = 2; i < args.length(); ++i) {
    101     Handle<Object> next_source = args.at(i);
    102     MAYBE_RETURN(JSReceiver::SetOrCopyDataProperties(isolate, to, next_source),
    103                  isolate->heap()->exception());
    104   }
    105   // 5. Return to.
    106   return *to;
    107 }
    108 
    109 // ES6 section 19.1.3.4 Object.prototype.propertyIsEnumerable ( V )
    110 BUILTIN(ObjectPrototypePropertyIsEnumerable) {
    111   HandleScope scope(isolate);
    112   Handle<JSReceiver> object;
    113   Handle<Name> name;
    114   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    115       isolate, name, Object::ToName(isolate, args.atOrUndefined(isolate, 1)));
    116   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    117       isolate, object, JSReceiver::ToObject(isolate, args.receiver()));
    118   Maybe<PropertyAttributes> maybe =
    119       JSReceiver::GetOwnPropertyAttributes(object, name);
    120   if (!maybe.IsJust()) return isolate->heap()->exception();
    121   if (maybe.FromJust() == ABSENT) return isolate->heap()->false_value();
    122   return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0);
    123 }
    124 
    125 void ObjectBuiltinsAssembler::IsString(Node* object, Label* if_string,
    126                                        Label* if_notstring) {
    127   Label if_notsmi(this);
    128   Branch(TaggedIsSmi(object), if_notstring, &if_notsmi);
    129 
    130   Bind(&if_notsmi);
    131   {
    132     Node* instance_type = LoadInstanceType(object);
    133 
    134     Branch(IsStringInstanceType(instance_type), if_string, if_notstring);
    135   }
    136 }
    137 
    138 void ObjectBuiltinsAssembler::ReturnToStringFormat(Node* context,
    139                                                    Node* string) {
    140   Node* lhs = HeapConstant(factory()->NewStringFromStaticChars("[object "));
    141   Node* rhs = HeapConstant(factory()->NewStringFromStaticChars("]"));
    142 
    143   Callable callable =
    144       CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
    145 
    146   Return(CallStub(callable, context, CallStub(callable, context, lhs, string),
    147                   rhs));
    148 }
    149 
    150 // ES6 section 19.1.3.6 Object.prototype.toString
    151 TF_BUILTIN(ObjectProtoToString, ObjectBuiltinsAssembler) {
    152   Label return_undefined(this, Label::kDeferred),
    153       return_null(this, Label::kDeferred),
    154       return_arguments(this, Label::kDeferred), return_array(this),
    155       return_api(this, Label::kDeferred), return_object(this),
    156       return_regexp(this), return_function(this), return_error(this),
    157       return_date(this), return_jsvalue(this),
    158       return_jsproxy(this, Label::kDeferred);
    159 
    160   Label if_isproxy(this, Label::kDeferred);
    161 
    162   Label checkstringtag(this);
    163   Label if_tostringtag(this), if_notostringtag(this);
    164 
    165   Node* receiver = Parameter(0);
    166   Node* context = Parameter(3);
    167 
    168   GotoIf(WordEqual(receiver, UndefinedConstant()), &return_undefined);
    169 
    170   GotoIf(WordEqual(receiver, NullConstant()), &return_null);
    171 
    172   Callable to_object = CodeFactory::ToObject(isolate());
    173   receiver = CallStub(to_object, context, receiver);
    174 
    175   Node* receiver_instance_type = LoadInstanceType(receiver);
    176 
    177   // for proxies, check IsArray before getting @@toStringTag
    178   Variable var_proxy_is_array(this, MachineRepresentation::kTagged);
    179   var_proxy_is_array.Bind(BooleanConstant(false));
    180 
    181   Branch(Word32Equal(receiver_instance_type, Int32Constant(JS_PROXY_TYPE)),
    182          &if_isproxy, &checkstringtag);
    183 
    184   Bind(&if_isproxy);
    185   {
    186     // This can throw
    187     var_proxy_is_array.Bind(
    188         CallRuntime(Runtime::kArrayIsArray, context, receiver));
    189     Goto(&checkstringtag);
    190   }
    191 
    192   Bind(&checkstringtag);
    193   {
    194     Node* to_string_tag_symbol =
    195         HeapConstant(isolate()->factory()->to_string_tag_symbol());
    196 
    197     GetPropertyStub stub(isolate());
    198     Callable get_property =
    199         Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
    200     Node* to_string_tag_value =
    201         CallStub(get_property, context, receiver, to_string_tag_symbol);
    202 
    203     IsString(to_string_tag_value, &if_tostringtag, &if_notostringtag);
    204 
    205     Bind(&if_tostringtag);
    206     ReturnToStringFormat(context, to_string_tag_value);
    207   }
    208   Bind(&if_notostringtag);
    209   {
    210     size_t const kNumCases = 11;
    211     Label* case_labels[kNumCases];
    212     int32_t case_values[kNumCases];
    213     case_labels[0] = &return_api;
    214     case_values[0] = JS_API_OBJECT_TYPE;
    215     case_labels[1] = &return_api;
    216     case_values[1] = JS_SPECIAL_API_OBJECT_TYPE;
    217     case_labels[2] = &return_arguments;
    218     case_values[2] = JS_ARGUMENTS_TYPE;
    219     case_labels[3] = &return_array;
    220     case_values[3] = JS_ARRAY_TYPE;
    221     case_labels[4] = &return_function;
    222     case_values[4] = JS_BOUND_FUNCTION_TYPE;
    223     case_labels[5] = &return_function;
    224     case_values[5] = JS_FUNCTION_TYPE;
    225     case_labels[6] = &return_error;
    226     case_values[6] = JS_ERROR_TYPE;
    227     case_labels[7] = &return_date;
    228     case_values[7] = JS_DATE_TYPE;
    229     case_labels[8] = &return_regexp;
    230     case_values[8] = JS_REGEXP_TYPE;
    231     case_labels[9] = &return_jsvalue;
    232     case_values[9] = JS_VALUE_TYPE;
    233     case_labels[10] = &return_jsproxy;
    234     case_values[10] = JS_PROXY_TYPE;
    235 
    236     Switch(receiver_instance_type, &return_object, case_values, case_labels,
    237            arraysize(case_values));
    238 
    239     Bind(&return_undefined);
    240     Return(HeapConstant(isolate()->factory()->undefined_to_string()));
    241 
    242     Bind(&return_null);
    243     Return(HeapConstant(isolate()->factory()->null_to_string()));
    244 
    245     Bind(&return_arguments);
    246     Return(HeapConstant(isolate()->factory()->arguments_to_string()));
    247 
    248     Bind(&return_array);
    249     Return(HeapConstant(isolate()->factory()->array_to_string()));
    250 
    251     Bind(&return_function);
    252     Return(HeapConstant(isolate()->factory()->function_to_string()));
    253 
    254     Bind(&return_error);
    255     Return(HeapConstant(isolate()->factory()->error_to_string()));
    256 
    257     Bind(&return_date);
    258     Return(HeapConstant(isolate()->factory()->date_to_string()));
    259 
    260     Bind(&return_regexp);
    261     Return(HeapConstant(isolate()->factory()->regexp_to_string()));
    262 
    263     Bind(&return_api);
    264     {
    265       Node* class_name = CallRuntime(Runtime::kClassOf, context, receiver);
    266       ReturnToStringFormat(context, class_name);
    267     }
    268 
    269     Bind(&return_jsvalue);
    270     {
    271       Label return_boolean(this), return_number(this), return_string(this);
    272 
    273       Node* value = LoadJSValueValue(receiver);
    274       GotoIf(TaggedIsSmi(value), &return_number);
    275       Node* instance_type = LoadInstanceType(value);
    276 
    277       GotoIf(IsStringInstanceType(instance_type), &return_string);
    278       GotoIf(Word32Equal(instance_type, Int32Constant(HEAP_NUMBER_TYPE)),
    279              &return_number);
    280       GotoIf(Word32Equal(instance_type, Int32Constant(ODDBALL_TYPE)),
    281              &return_boolean);
    282 
    283       CSA_ASSERT(this, Word32Equal(instance_type, Int32Constant(SYMBOL_TYPE)));
    284       Goto(&return_object);
    285 
    286       Bind(&return_string);
    287       Return(HeapConstant(isolate()->factory()->string_to_string()));
    288 
    289       Bind(&return_number);
    290       Return(HeapConstant(isolate()->factory()->number_to_string()));
    291 
    292       Bind(&return_boolean);
    293       Return(HeapConstant(isolate()->factory()->boolean_to_string()));
    294     }
    295 
    296     Bind(&return_jsproxy);
    297     {
    298       GotoIf(WordEqual(var_proxy_is_array.value(), BooleanConstant(true)),
    299              &return_array);
    300 
    301       Node* map = LoadMap(receiver);
    302 
    303       // Return object if the proxy {receiver} is not callable.
    304       Branch(IsCallableMap(map), &return_function, &return_object);
    305     }
    306 
    307     // Default
    308     Bind(&return_object);
    309     Return(HeapConstant(isolate()->factory()->object_to_string()));
    310   }
    311 }
    312 
    313 TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) {
    314   Node* prototype = Parameter(1);
    315   Node* properties = Parameter(2);
    316   Node* context = Parameter(3 + 2);
    317 
    318   Label call_runtime(this, Label::kDeferred), prototype_valid(this),
    319       no_properties(this);
    320   {
    321     Comment("Argument 1 check: prototype");
    322     GotoIf(WordEqual(prototype, NullConstant()), &prototype_valid);
    323     BranchIfJSReceiver(prototype, &prototype_valid, &call_runtime);
    324   }
    325 
    326   Bind(&prototype_valid);
    327   {
    328     Comment("Argument 2 check: properties");
    329     // Check that we have a simple object
    330     GotoIf(TaggedIsSmi(properties), &call_runtime);
    331     // Undefined implies no properties.
    332     GotoIf(WordEqual(properties, UndefinedConstant()), &no_properties);
    333     Node* properties_map = LoadMap(properties);
    334     GotoIf(IsSpecialReceiverMap(properties_map), &call_runtime);
    335     // Stay on the fast path only if there are no elements.
    336     GotoIfNot(WordEqual(LoadElements(properties),
    337                         LoadRoot(Heap::kEmptyFixedArrayRootIndex)),
    338               &call_runtime);
    339     // Handle dictionary objects or fast objects with properties in runtime.
    340     Node* bit_field3 = LoadMapBitField3(properties_map);
    341     GotoIf(IsSetWord32<Map::DictionaryMap>(bit_field3), &call_runtime);
    342     Branch(IsSetWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3),
    343            &call_runtime, &no_properties);
    344   }
    345 
    346   // Create a new object with the given prototype.
    347   Bind(&no_properties);
    348   {
    349     Variable map(this, MachineRepresentation::kTagged);
    350     Variable properties(this, MachineRepresentation::kTagged);
    351     Label non_null_proto(this), instantiate_map(this), good(this);
    352 
    353     Branch(WordEqual(prototype, NullConstant()), &good, &non_null_proto);
    354 
    355     Bind(&good);
    356     {
    357       map.Bind(LoadContextElement(
    358           context, Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP));
    359       properties.Bind(AllocateNameDictionary(NameDictionary::kInitialCapacity));
    360       Goto(&instantiate_map);
    361     }
    362 
    363     Bind(&non_null_proto);
    364     {
    365       properties.Bind(EmptyFixedArrayConstant());
    366       Node* object_function =
    367           LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX);
    368       Node* object_function_map = LoadObjectField(
    369           object_function, JSFunction::kPrototypeOrInitialMapOffset);
    370       map.Bind(object_function_map);
    371       GotoIf(WordEqual(prototype, LoadMapPrototype(map.value())),
    372              &instantiate_map);
    373       // Try loading the prototype info.
    374       Node* prototype_info =
    375           LoadMapPrototypeInfo(LoadMap(prototype), &call_runtime);
    376       Comment("Load ObjectCreateMap from PrototypeInfo");
    377       Node* weak_cell =
    378           LoadObjectField(prototype_info, PrototypeInfo::kObjectCreateMap);
    379       GotoIf(WordEqual(weak_cell, UndefinedConstant()), &call_runtime);
    380       map.Bind(LoadWeakCellValue(weak_cell, &call_runtime));
    381       Goto(&instantiate_map);
    382     }
    383 
    384     Bind(&instantiate_map);
    385     {
    386       Node* instance = AllocateJSObjectFromMap(map.value(), properties.value());
    387       Return(instance);
    388     }
    389   }
    390 
    391   Bind(&call_runtime);
    392   {
    393     Return(CallRuntime(Runtime::kObjectCreate, context, prototype, properties));
    394   }
    395 }
    396 
    397 // ES6 section 19.1.2.3 Object.defineProperties
    398 BUILTIN(ObjectDefineProperties) {
    399   HandleScope scope(isolate);
    400   DCHECK_EQ(3, args.length());
    401   Handle<Object> target = args.at(1);
    402   Handle<Object> properties = args.at(2);
    403 
    404   RETURN_RESULT_OR_FAILURE(
    405       isolate, JSReceiver::DefineProperties(isolate, target, properties));
    406 }
    407 
    408 // ES6 section 19.1.2.4 Object.defineProperty
    409 BUILTIN(ObjectDefineProperty) {
    410   HandleScope scope(isolate);
    411   DCHECK_EQ(4, args.length());
    412   Handle<Object> target = args.at(1);
    413   Handle<Object> key = args.at(2);
    414   Handle<Object> attributes = args.at(3);
    415 
    416   return JSReceiver::DefineProperty(isolate, target, key, attributes);
    417 }
    418 
    419 namespace {
    420 
    421 template <AccessorComponent which_accessor>
    422 Object* ObjectDefineAccessor(Isolate* isolate, Handle<Object> object,
    423                              Handle<Object> name, Handle<Object> accessor) {
    424   // 1. Let O be ? ToObject(this value).
    425   Handle<JSReceiver> receiver;
    426   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
    427                                      Object::ConvertReceiver(isolate, object));
    428   // 2. If IsCallable(getter) is false, throw a TypeError exception.
    429   if (!accessor->IsCallable()) {
    430     MessageTemplate::Template message =
    431         which_accessor == ACCESSOR_GETTER
    432             ? MessageTemplate::kObjectGetterExpectingFunction
    433             : MessageTemplate::kObjectSetterExpectingFunction;
    434     THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewTypeError(message));
    435   }
    436   // 3. Let desc be PropertyDescriptor{[[Get]]: getter, [[Enumerable]]: true,
    437   //                                   [[Configurable]]: true}.
    438   PropertyDescriptor desc;
    439   if (which_accessor == ACCESSOR_GETTER) {
    440     desc.set_get(accessor);
    441   } else {
    442     DCHECK(which_accessor == ACCESSOR_SETTER);
    443     desc.set_set(accessor);
    444   }
    445   desc.set_enumerable(true);
    446   desc.set_configurable(true);
    447   // 4. Let key be ? ToPropertyKey(P).
    448   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
    449                                      Object::ToPropertyKey(isolate, name));
    450   // 5. Perform ? DefinePropertyOrThrow(O, key, desc).
    451   // To preserve legacy behavior, we ignore errors silently rather than
    452   // throwing an exception.
    453   Maybe<bool> success = JSReceiver::DefineOwnProperty(
    454       isolate, receiver, name, &desc, Object::DONT_THROW);
    455   MAYBE_RETURN(success, isolate->heap()->exception());
    456   if (!success.FromJust()) {
    457     isolate->CountUsage(v8::Isolate::kDefineGetterOrSetterWouldThrow);
    458   }
    459   // 6. Return undefined.
    460   return isolate->heap()->undefined_value();
    461 }
    462 
    463 Object* ObjectLookupAccessor(Isolate* isolate, Handle<Object> object,
    464                              Handle<Object> key, AccessorComponent component) {
    465   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, object,
    466                                      Object::ConvertReceiver(isolate, object));
    467   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
    468                                      Object::ToPropertyKey(isolate, key));
    469   bool success = false;
    470   LookupIterator it = LookupIterator::PropertyOrElement(
    471       isolate, object, key, &success,
    472       LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
    473   DCHECK(success);
    474 
    475   for (; it.IsFound(); it.Next()) {
    476     switch (it.state()) {
    477       case LookupIterator::INTERCEPTOR:
    478       case LookupIterator::NOT_FOUND:
    479       case LookupIterator::TRANSITION:
    480         UNREACHABLE();
    481 
    482       case LookupIterator::ACCESS_CHECK:
    483         if (it.HasAccess()) continue;
    484         isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
    485         RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
    486         return isolate->heap()->undefined_value();
    487 
    488       case LookupIterator::JSPROXY: {
    489         PropertyDescriptor desc;
    490         Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
    491             isolate, it.GetHolder<JSProxy>(), it.GetName(), &desc);
    492         MAYBE_RETURN(found, isolate->heap()->exception());
    493         if (found.FromJust()) {
    494           if (component == ACCESSOR_GETTER && desc.has_get()) {
    495             return *desc.get();
    496           }
    497           if (component == ACCESSOR_SETTER && desc.has_set()) {
    498             return *desc.set();
    499           }
    500           return isolate->heap()->undefined_value();
    501         }
    502         Handle<Object> prototype;
    503         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    504             isolate, prototype, JSProxy::GetPrototype(it.GetHolder<JSProxy>()));
    505         if (prototype->IsNull(isolate)) {
    506           return isolate->heap()->undefined_value();
    507         }
    508         return ObjectLookupAccessor(isolate, prototype, key, component);
    509       }
    510 
    511       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    512       case LookupIterator::DATA:
    513         return isolate->heap()->undefined_value();
    514 
    515       case LookupIterator::ACCESSOR: {
    516         Handle<Object> maybe_pair = it.GetAccessors();
    517         if (maybe_pair->IsAccessorPair()) {
    518           return *AccessorPair::GetComponent(
    519               Handle<AccessorPair>::cast(maybe_pair), component);
    520         }
    521       }
    522     }
    523   }
    524 
    525   return isolate->heap()->undefined_value();
    526 }
    527 
    528 }  // namespace
    529 
    530 // ES6 B.2.2.2 a.k.a.
    531 // https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
    532 BUILTIN(ObjectDefineGetter) {
    533   HandleScope scope(isolate);
    534   Handle<Object> object = args.at(0);  // Receiver.
    535   Handle<Object> name = args.at(1);
    536   Handle<Object> getter = args.at(2);
    537   return ObjectDefineAccessor<ACCESSOR_GETTER>(isolate, object, name, getter);
    538 }
    539 
    540 // ES6 B.2.2.3 a.k.a.
    541 // https://tc39.github.io/ecma262/#sec-object.prototype.__defineSetter__
    542 BUILTIN(ObjectDefineSetter) {
    543   HandleScope scope(isolate);
    544   Handle<Object> object = args.at(0);  // Receiver.
    545   Handle<Object> name = args.at(1);
    546   Handle<Object> setter = args.at(2);
    547   return ObjectDefineAccessor<ACCESSOR_SETTER>(isolate, object, name, setter);
    548 }
    549 
    550 // ES6 B.2.2.4 a.k.a.
    551 // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupGetter__
    552 BUILTIN(ObjectLookupGetter) {
    553   HandleScope scope(isolate);
    554   Handle<Object> object = args.at(0);
    555   Handle<Object> name = args.at(1);
    556   return ObjectLookupAccessor(isolate, object, name, ACCESSOR_GETTER);
    557 }
    558 
    559 // ES6 B.2.2.5 a.k.a.
    560 // https://tc39.github.io/ecma262/#sec-object.prototype.__lookupSetter__
    561 BUILTIN(ObjectLookupSetter) {
    562   HandleScope scope(isolate);
    563   Handle<Object> object = args.at(0);
    564   Handle<Object> name = args.at(1);
    565   return ObjectLookupAccessor(isolate, object, name, ACCESSOR_SETTER);
    566 }
    567 
    568 // ES6 section 19.1.2.5 Object.freeze ( O )
    569 BUILTIN(ObjectFreeze) {
    570   HandleScope scope(isolate);
    571   Handle<Object> object = args.atOrUndefined(isolate, 1);
    572   if (object->IsJSReceiver()) {
    573     MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
    574                                                FROZEN, Object::THROW_ON_ERROR),
    575                  isolate->heap()->exception());
    576   }
    577   return *object;
    578 }
    579 
    580 // ES section 19.1.2.9 Object.getPrototypeOf ( O )
    581 BUILTIN(ObjectGetPrototypeOf) {
    582   HandleScope scope(isolate);
    583   Handle<Object> object = args.atOrUndefined(isolate, 1);
    584 
    585   Handle<JSReceiver> receiver;
    586   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
    587                                      Object::ToObject(isolate, object));
    588 
    589   RETURN_RESULT_OR_FAILURE(isolate,
    590                            JSReceiver::GetPrototype(isolate, receiver));
    591 }
    592 
    593 // ES6 section 19.1.2.21 Object.setPrototypeOf ( O, proto )
    594 BUILTIN(ObjectSetPrototypeOf) {
    595   HandleScope scope(isolate);
    596 
    597   // 1. Let O be ? RequireObjectCoercible(O).
    598   Handle<Object> object = args.atOrUndefined(isolate, 1);
    599   if (object->IsNullOrUndefined(isolate)) {
    600     THROW_NEW_ERROR_RETURN_FAILURE(
    601         isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
    602                               isolate->factory()->NewStringFromAsciiChecked(
    603                                   "Object.setPrototypeOf")));
    604   }
    605 
    606   // 2. If Type(proto) is neither Object nor Null, throw a TypeError exception.
    607   Handle<Object> proto = args.atOrUndefined(isolate, 2);
    608   if (!proto->IsNull(isolate) && !proto->IsJSReceiver()) {
    609     THROW_NEW_ERROR_RETURN_FAILURE(
    610         isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
    611   }
    612 
    613   // 3. If Type(O) is not Object, return O.
    614   if (!object->IsJSReceiver()) return *object;
    615   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
    616 
    617   // 4. Let status be ? O.[[SetPrototypeOf]](proto).
    618   // 5. If status is false, throw a TypeError exception.
    619   MAYBE_RETURN(
    620       JSReceiver::SetPrototype(receiver, proto, true, Object::THROW_ON_ERROR),
    621       isolate->heap()->exception());
    622 
    623   // 6. Return O.
    624   return *receiver;
    625 }
    626 
    627 // ES6 section B.2.2.1.1 get Object.prototype.__proto__
    628 BUILTIN(ObjectPrototypeGetProto) {
    629   HandleScope scope(isolate);
    630   // 1. Let O be ? ToObject(this value).
    631   Handle<JSReceiver> receiver;
    632   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    633       isolate, receiver, Object::ToObject(isolate, args.receiver()));
    634 
    635   // 2. Return ? O.[[GetPrototypeOf]]().
    636   RETURN_RESULT_OR_FAILURE(isolate,
    637                            JSReceiver::GetPrototype(isolate, receiver));
    638 }
    639 
    640 // ES6 section B.2.2.1.2 set Object.prototype.__proto__
    641 BUILTIN(ObjectPrototypeSetProto) {
    642   HandleScope scope(isolate);
    643   // 1. Let O be ? RequireObjectCoercible(this value).
    644   Handle<Object> object = args.receiver();
    645   if (object->IsNullOrUndefined(isolate)) {
    646     THROW_NEW_ERROR_RETURN_FAILURE(
    647         isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
    648                               isolate->factory()->NewStringFromAsciiChecked(
    649                                   "set Object.prototype.__proto__")));
    650   }
    651 
    652   // 2. If Type(proto) is neither Object nor Null, return undefined.
    653   Handle<Object> proto = args.at(1);
    654   if (!proto->IsNull(isolate) && !proto->IsJSReceiver()) {
    655     return isolate->heap()->undefined_value();
    656   }
    657 
    658   // 3. If Type(O) is not Object, return undefined.
    659   if (!object->IsJSReceiver()) return isolate->heap()->undefined_value();
    660   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
    661 
    662   // 4. Let status be ? O.[[SetPrototypeOf]](proto).
    663   // 5. If status is false, throw a TypeError exception.
    664   MAYBE_RETURN(
    665       JSReceiver::SetPrototype(receiver, proto, true, Object::THROW_ON_ERROR),
    666       isolate->heap()->exception());
    667 
    668   // Return undefined.
    669   return isolate->heap()->undefined_value();
    670 }
    671 
    672 // ES6 section 19.1.2.6 Object.getOwnPropertyDescriptor ( O, P )
    673 BUILTIN(ObjectGetOwnPropertyDescriptor) {
    674   HandleScope scope(isolate);
    675   // 1. Let obj be ? ToObject(O).
    676   Handle<Object> object = args.atOrUndefined(isolate, 1);
    677   Handle<JSReceiver> receiver;
    678   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
    679                                      Object::ToObject(isolate, object));
    680   // 2. Let key be ? ToPropertyKey(P).
    681   Handle<Object> property = args.atOrUndefined(isolate, 2);
    682   Handle<Name> key;
    683   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key,
    684                                      Object::ToName(isolate, property));
    685   // 3. Let desc be ? obj.[[GetOwnProperty]](key).
    686   PropertyDescriptor desc;
    687   Maybe<bool> found =
    688       JSReceiver::GetOwnPropertyDescriptor(isolate, receiver, key, &desc);
    689   MAYBE_RETURN(found, isolate->heap()->exception());
    690   // 4. Return FromPropertyDescriptor(desc).
    691   if (!found.FromJust()) return isolate->heap()->undefined_value();
    692   return *desc.ToObject(isolate);
    693 }
    694 
    695 namespace {
    696 
    697 Object* GetOwnPropertyKeys(Isolate* isolate, BuiltinArguments args,
    698                            PropertyFilter filter) {
    699   HandleScope scope(isolate);
    700   Handle<Object> object = args.atOrUndefined(isolate, 1);
    701   Handle<JSReceiver> receiver;
    702   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
    703                                      Object::ToObject(isolate, object));
    704   Handle<FixedArray> keys;
    705   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    706       isolate, keys,
    707       KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly, filter,
    708                               GetKeysConversion::kConvertToString));
    709   return *isolate->factory()->NewJSArrayWithElements(keys);
    710 }
    711 
    712 }  // namespace
    713 
    714 // ES6 section 19.1.2.7 Object.getOwnPropertyNames ( O )
    715 BUILTIN(ObjectGetOwnPropertyNames) {
    716   return GetOwnPropertyKeys(isolate, args, SKIP_SYMBOLS);
    717 }
    718 
    719 // ES6 section 19.1.2.8 Object.getOwnPropertySymbols ( O )
    720 BUILTIN(ObjectGetOwnPropertySymbols) {
    721   return GetOwnPropertyKeys(isolate, args, SKIP_STRINGS);
    722 }
    723 
    724 // ES#sec-object.is Object.is ( value1, value2 )
    725 BUILTIN(ObjectIs) {
    726   SealHandleScope shs(isolate);
    727   DCHECK_EQ(3, args.length());
    728   Handle<Object> value1 = args.at(1);
    729   Handle<Object> value2 = args.at(2);
    730   return isolate->heap()->ToBoolean(value1->SameValue(*value2));
    731 }
    732 
    733 // ES6 section 19.1.2.11 Object.isExtensible ( O )
    734 BUILTIN(ObjectIsExtensible) {
    735   HandleScope scope(isolate);
    736   Handle<Object> object = args.atOrUndefined(isolate, 1);
    737   Maybe<bool> result =
    738       object->IsJSReceiver()
    739           ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
    740           : Just(false);
    741   MAYBE_RETURN(result, isolate->heap()->exception());
    742   return isolate->heap()->ToBoolean(result.FromJust());
    743 }
    744 
    745 // ES6 section 19.1.2.12 Object.isFrozen ( O )
    746 BUILTIN(ObjectIsFrozen) {
    747   HandleScope scope(isolate);
    748   Handle<Object> object = args.atOrUndefined(isolate, 1);
    749   Maybe<bool> result = object->IsJSReceiver()
    750                            ? JSReceiver::TestIntegrityLevel(
    751                                  Handle<JSReceiver>::cast(object), FROZEN)
    752                            : Just(true);
    753   MAYBE_RETURN(result, isolate->heap()->exception());
    754   return isolate->heap()->ToBoolean(result.FromJust());
    755 }
    756 
    757 // ES6 section 19.1.2.13 Object.isSealed ( O )
    758 BUILTIN(ObjectIsSealed) {
    759   HandleScope scope(isolate);
    760   Handle<Object> object = args.atOrUndefined(isolate, 1);
    761   Maybe<bool> result = object->IsJSReceiver()
    762                            ? JSReceiver::TestIntegrityLevel(
    763                                  Handle<JSReceiver>::cast(object), SEALED)
    764                            : Just(true);
    765   MAYBE_RETURN(result, isolate->heap()->exception());
    766   return isolate->heap()->ToBoolean(result.FromJust());
    767 }
    768 
    769 // ES6 section 19.1.2.14 Object.keys ( O )
    770 BUILTIN(ObjectKeys) {
    771   HandleScope scope(isolate);
    772   Handle<Object> object = args.atOrUndefined(isolate, 1);
    773   Handle<JSReceiver> receiver;
    774   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
    775                                      Object::ToObject(isolate, object));
    776 
    777   Handle<FixedArray> keys;
    778   int enum_length = receiver->map()->EnumLength();
    779   if (enum_length != kInvalidEnumCacheSentinel &&
    780       JSObject::cast(*receiver)->elements() ==
    781           isolate->heap()->empty_fixed_array()) {
    782     DCHECK(receiver->IsJSObject());
    783     DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor());
    784     DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded());
    785     DCHECK(!receiver->map()->has_hidden_prototype());
    786     DCHECK(JSObject::cast(*receiver)->HasFastProperties());
    787     if (enum_length == 0) {
    788       keys = isolate->factory()->empty_fixed_array();
    789     } else {
    790       Handle<FixedArray> cache(
    791           receiver->map()->instance_descriptors()->GetEnumCache());
    792       keys = isolate->factory()->CopyFixedArrayUpTo(cache, enum_length);
    793     }
    794   } else {
    795     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    796         isolate, keys,
    797         KeyAccumulator::GetKeys(receiver, KeyCollectionMode::kOwnOnly,
    798                                 ENUMERABLE_STRINGS,
    799                                 GetKeysConversion::kConvertToString));
    800   }
    801   return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
    802 }
    803 
    804 BUILTIN(ObjectValues) {
    805   HandleScope scope(isolate);
    806   Handle<Object> object = args.atOrUndefined(isolate, 1);
    807   Handle<JSReceiver> receiver;
    808   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
    809                                      Object::ToObject(isolate, object));
    810   Handle<FixedArray> values;
    811   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    812       isolate, values, JSReceiver::GetOwnValues(receiver, ENUMERABLE_STRINGS));
    813   return *isolate->factory()->NewJSArrayWithElements(values);
    814 }
    815 
    816 BUILTIN(ObjectEntries) {
    817   HandleScope scope(isolate);
    818   Handle<Object> object = args.atOrUndefined(isolate, 1);
    819   Handle<JSReceiver> receiver;
    820   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
    821                                      Object::ToObject(isolate, object));
    822   Handle<FixedArray> entries;
    823   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    824       isolate, entries,
    825       JSReceiver::GetOwnEntries(receiver, ENUMERABLE_STRINGS));
    826   return *isolate->factory()->NewJSArrayWithElements(entries);
    827 }
    828 
    829 BUILTIN(ObjectGetOwnPropertyDescriptors) {
    830   HandleScope scope(isolate);
    831   Handle<Object> object = args.atOrUndefined(isolate, 1);
    832 
    833   Handle<JSReceiver> receiver;
    834   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
    835                                      Object::ToObject(isolate, object));
    836 
    837   Handle<FixedArray> keys;
    838   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
    839       isolate, keys, KeyAccumulator::GetKeys(
    840                          receiver, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
    841                          GetKeysConversion::kConvertToString));
    842 
    843   Handle<JSObject> descriptors =
    844       isolate->factory()->NewJSObject(isolate->object_function());
    845 
    846   for (int i = 0; i < keys->length(); ++i) {
    847     Handle<Name> key = Handle<Name>::cast(FixedArray::get(*keys, i, isolate));
    848     PropertyDescriptor descriptor;
    849     Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
    850         isolate, receiver, key, &descriptor);
    851     MAYBE_RETURN(did_get_descriptor, isolate->heap()->exception());
    852 
    853     if (!did_get_descriptor.FromJust()) continue;
    854     Handle<Object> from_descriptor = descriptor.ToObject(isolate);
    855 
    856     LookupIterator it = LookupIterator::PropertyOrElement(
    857         isolate, descriptors, key, descriptors, LookupIterator::OWN);
    858     Maybe<bool> success = JSReceiver::CreateDataProperty(&it, from_descriptor,
    859                                                          Object::DONT_THROW);
    860     CHECK(success.FromJust());
    861   }
    862 
    863   return *descriptors;
    864 }
    865 
    866 // ES6 section 19.1.2.15 Object.preventExtensions ( O )
    867 BUILTIN(ObjectPreventExtensions) {
    868   HandleScope scope(isolate);
    869   Handle<Object> object = args.atOrUndefined(isolate, 1);
    870   if (object->IsJSReceiver()) {
    871     MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
    872                                                Object::THROW_ON_ERROR),
    873                  isolate->heap()->exception());
    874   }
    875   return *object;
    876 }
    877 
    878 // ES6 section 19.1.2.17 Object.seal ( O )
    879 BUILTIN(ObjectSeal) {
    880   HandleScope scope(isolate);
    881   Handle<Object> object = args.atOrUndefined(isolate, 1);
    882   if (object->IsJSReceiver()) {
    883     MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
    884                                                SEALED, Object::THROW_ON_ERROR),
    885                  isolate->heap()->exception());
    886   }
    887   return *object;
    888 }
    889 
    890 TF_BUILTIN(CreateIterResultObject, ObjectBuiltinsAssembler) {
    891   typedef CreateIterResultObjectDescriptor Descriptor;
    892 
    893   Node* const value = Parameter(Descriptor::kValue);
    894   Node* const done = Parameter(Descriptor::kDone);
    895   Node* const context = Parameter(Descriptor::kContext);
    896 
    897   Node* const native_context = LoadNativeContext(context);
    898   Node* const map =
    899       LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
    900 
    901   Node* const result = AllocateJSObjectFromMap(map);
    902 
    903   StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kValueOffset, value);
    904   StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kDoneOffset, done);
    905 
    906   Return(result);
    907 }
    908 
    909 TF_BUILTIN(HasProperty, ObjectBuiltinsAssembler) {
    910   typedef HasPropertyDescriptor Descriptor;
    911 
    912   Node* key = Parameter(Descriptor::kKey);
    913   Node* object = Parameter(Descriptor::kObject);
    914   Node* context = Parameter(Descriptor::kContext);
    915 
    916   Return(HasProperty(object, key, context, Runtime::kHasProperty));
    917 }
    918 
    919 TF_BUILTIN(ForInFilter, ObjectBuiltinsAssembler) {
    920   typedef ForInFilterDescriptor Descriptor;
    921 
    922   Node* key = Parameter(Descriptor::kKey);
    923   Node* object = Parameter(Descriptor::kObject);
    924   Node* context = Parameter(Descriptor::kContext);
    925 
    926   Return(ForInFilter(key, object, context));
    927 }
    928 
    929 TF_BUILTIN(ForInNext, ObjectBuiltinsAssembler) {
    930   typedef ForInNextDescriptor Descriptor;
    931 
    932   Label filter(this);
    933   Node* object = Parameter(Descriptor::kObject);
    934   Node* cache_array = Parameter(Descriptor::kCacheArray);
    935   Node* cache_type = Parameter(Descriptor::kCacheType);
    936   Node* index = Parameter(Descriptor::kIndex);
    937   Node* context = Parameter(Descriptor::kContext);
    938 
    939   Node* key = LoadFixedArrayElement(cache_array, SmiUntag(index));
    940   Node* map = LoadMap(object);
    941   GotoIfNot(WordEqual(map, cache_type), &filter);
    942   Return(key);
    943   Bind(&filter);
    944   Return(ForInFilter(key, object, context));
    945 }
    946 
    947 TF_BUILTIN(ForInPrepare, ObjectBuiltinsAssembler) {
    948   typedef ForInPrepareDescriptor Descriptor;
    949 
    950   Label call_runtime(this), nothing_to_iterate(this);
    951   Node* object = Parameter(Descriptor::kObject);
    952   Node* context = Parameter(Descriptor::kContext);
    953 
    954   Node* cache_type;
    955   Node* cache_array;
    956   Node* cache_length;
    957   std::tie(cache_type, cache_array, cache_length) =
    958       EmitForInPrepare(object, context, &call_runtime, &nothing_to_iterate);
    959 
    960   Return(cache_type, cache_array, cache_length);
    961 
    962   Bind(&call_runtime);
    963   TailCallRuntime(Runtime::kForInPrepare, context, object);
    964 
    965   Bind(&nothing_to_iterate);
    966   {
    967     Node* zero = SmiConstant(0);
    968     Return(zero, zero, zero);
    969   }
    970 }
    971 
    972 TF_BUILTIN(InstanceOf, ObjectBuiltinsAssembler) {
    973   typedef CompareDescriptor Descriptor;
    974 
    975   Node* object = Parameter(Descriptor::kLeft);
    976   Node* callable = Parameter(Descriptor::kRight);
    977   Node* context = Parameter(Descriptor::kContext);
    978 
    979   Return(InstanceOf(object, callable, context));
    980 }
    981 
    982 // ES6 section 7.3.19 OrdinaryHasInstance ( C, O )
    983 TF_BUILTIN(OrdinaryHasInstance, ObjectBuiltinsAssembler) {
    984   typedef CompareDescriptor Descriptor;
    985 
    986   Node* constructor = Parameter(Descriptor::kLeft);
    987   Node* object = Parameter(Descriptor::kRight);
    988   Node* context = Parameter(Descriptor::kContext);
    989 
    990   Return(OrdinaryHasInstance(context, constructor, object));
    991 }
    992 
    993 TF_BUILTIN(GetSuperConstructor, ObjectBuiltinsAssembler) {
    994   typedef TypeofDescriptor Descriptor;
    995 
    996   Node* object = Parameter(Descriptor::kObject);
    997   Node* context = Parameter(Descriptor::kContext);
    998 
    999   Return(GetSuperConstructor(object, context));
   1000 }
   1001 
   1002 }  // namespace internal
   1003 }  // namespace v8
   1004