LCOV - code coverage report
Current view: top level - src/builtins - builtins-object-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 454 454 100.0 %
Date: 2017-10-20 Functions: 35 35 100.0 %

          Line data    Source code
       1             : // Copyright 2017 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-utils-gen.h"
       6             : #include "src/builtins/builtins.h"
       7             : #include "src/code-stub-assembler.h"
       8             : #include "src/factory-inl.h"
       9             : #include "src/objects/property-descriptor-object.h"
      10             : #include "src/objects/shared-function-info.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : // -----------------------------------------------------------------------------
      16             : // ES6 section 19.1 Object Objects
      17             : 
      18             : typedef compiler::Node Node;
      19             : 
      20             : class ObjectBuiltinsAssembler : public CodeStubAssembler {
      21             :  public:
      22             :   explicit ObjectBuiltinsAssembler(compiler::CodeAssemblerState* state)
      23         403 :       : CodeStubAssembler(state) {}
      24             : 
      25             :  protected:
      26             :   void ReturnToStringFormat(Node* context, Node* string);
      27             :   void AddToDictionaryIf(Node* condition, Node* name_dictionary,
      28             :                          Handle<Name> name, Node* value, Label* bailout);
      29             :   Node* FromPropertyDescriptor(Node* context, Node* desc);
      30             :   Node* FromPropertyDetails(Node* context, Node* raw_value, Node* details,
      31             :                             Label* if_bailout);
      32             :   Node* ConstructAccessorDescriptor(Node* context, Node* getter, Node* setter,
      33             :                                     Node* enumerable, Node* configurable);
      34             :   Node* ConstructDataDescriptor(Node* context, Node* value, Node* writable,
      35             :                                 Node* enumerable, Node* configurable);
      36             :   Node* GetAccessorOrUndefined(Node* accessor, Label* if_bailout);
      37             : };
      38             : 
      39          93 : void ObjectBuiltinsAssembler::ReturnToStringFormat(Node* context,
      40             :                                                    Node* string) {
      41         186 :   Node* lhs = StringConstant("[object ");
      42         186 :   Node* rhs = StringConstant("]");
      43             : 
      44             :   Callable callable =
      45          93 :       CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
      46             : 
      47             :   Return(CallStub(callable, context, CallStub(callable, context, lhs, string),
      48         186 :                   rhs));
      49          93 : }
      50             : 
      51          62 : Node* ObjectBuiltinsAssembler::ConstructAccessorDescriptor(Node* context,
      52             :                                                            Node* getter,
      53             :                                                            Node* setter,
      54             :                                                            Node* enumerable,
      55             :                                                            Node* configurable) {
      56         124 :   Node* native_context = LoadNativeContext(context);
      57             :   Node* map = LoadContextElement(
      58         124 :       native_context, Context::ACCESSOR_PROPERTY_DESCRIPTOR_MAP_INDEX);
      59          62 :   Node* js_desc = AllocateJSObjectFromMap(map);
      60             : 
      61             :   StoreObjectFieldNoWriteBarrier(
      62          62 :       js_desc, JSAccessorPropertyDescriptor::kGetOffset, getter);
      63             :   StoreObjectFieldNoWriteBarrier(
      64          62 :       js_desc, JSAccessorPropertyDescriptor::kSetOffset, setter);
      65             :   StoreObjectFieldNoWriteBarrier(
      66             :       js_desc, JSAccessorPropertyDescriptor::kEnumerableOffset,
      67          62 :       SelectBooleanConstant(enumerable));
      68             :   StoreObjectFieldNoWriteBarrier(
      69             :       js_desc, JSAccessorPropertyDescriptor::kConfigurableOffset,
      70          62 :       SelectBooleanConstant(configurable));
      71             : 
      72          62 :   return js_desc;
      73             : }
      74             : 
      75          62 : Node* ObjectBuiltinsAssembler::ConstructDataDescriptor(Node* context,
      76             :                                                        Node* value,
      77             :                                                        Node* writable,
      78             :                                                        Node* enumerable,
      79             :                                                        Node* configurable) {
      80         124 :   Node* native_context = LoadNativeContext(context);
      81             :   Node* map = LoadContextElement(native_context,
      82         124 :                                  Context::DATA_PROPERTY_DESCRIPTOR_MAP_INDEX);
      83          62 :   Node* js_desc = AllocateJSObjectFromMap(map);
      84             : 
      85             :   StoreObjectFieldNoWriteBarrier(js_desc,
      86          62 :                                  JSDataPropertyDescriptor::kValueOffset, value);
      87             :   StoreObjectFieldNoWriteBarrier(js_desc,
      88             :                                  JSDataPropertyDescriptor::kWritableOffset,
      89          62 :                                  SelectBooleanConstant(writable));
      90             :   StoreObjectFieldNoWriteBarrier(js_desc,
      91             :                                  JSDataPropertyDescriptor::kEnumerableOffset,
      92          62 :                                  SelectBooleanConstant(enumerable));
      93             :   StoreObjectFieldNoWriteBarrier(js_desc,
      94             :                                  JSDataPropertyDescriptor::kConfigurableOffset,
      95          62 :                                  SelectBooleanConstant(configurable));
      96             : 
      97          62 :   return js_desc;
      98             : }
      99             : 
     100         124 : TF_BUILTIN(ObjectPrototypeHasOwnProperty, ObjectBuiltinsAssembler) {
     101             :   Node* object = Parameter(Descriptor::kReceiver);
     102             :   Node* key = Parameter(Descriptor::kKey);
     103             :   Node* context = Parameter(Descriptor::kContext);
     104             : 
     105          31 :   Label call_runtime(this), return_true(this), return_false(this),
     106          31 :       to_primitive(this);
     107             : 
     108             :   // Smi receivers do not have own properties, just perform ToPrimitive on the
     109             :   // key.
     110          31 :   Label if_objectisnotsmi(this);
     111          62 :   Branch(TaggedIsSmi(object), &to_primitive, &if_objectisnotsmi);
     112          31 :   BIND(&if_objectisnotsmi);
     113             : 
     114          62 :   Node* map = LoadMap(object);
     115          62 :   Node* instance_type = LoadMapInstanceType(map);
     116             : 
     117             :   {
     118          31 :     VARIABLE(var_index, MachineType::PointerRepresentation());
     119          62 :     VARIABLE(var_unique, MachineRepresentation::kTagged);
     120             : 
     121          31 :     Label if_index(this), if_unique_name(this), if_notunique_name(this);
     122             :     TryToName(key, &if_index, &var_index, &if_unique_name, &var_unique,
     123          31 :               &call_runtime, &if_notunique_name);
     124             : 
     125          31 :     BIND(&if_unique_name);
     126             :     TryHasOwnProperty(object, map, instance_type, var_unique.value(),
     127          31 :                       &return_true, &return_false, &call_runtime);
     128             : 
     129          31 :     BIND(&if_index);
     130             :     {
     131             :       // Handle negative keys in the runtime.
     132          93 :       GotoIf(IntPtrLessThan(var_index.value(), IntPtrConstant(0)),
     133          62 :              &call_runtime);
     134             :       TryLookupElement(object, map, instance_type, var_index.value(),
     135             :                        &return_true, &return_false, &return_false,
     136          31 :                        &call_runtime);
     137             :     }
     138             : 
     139          31 :     BIND(&if_notunique_name);
     140             :     {
     141             :       Label not_in_string_table(this);
     142             :       TryInternalizeString(key, &if_index, &var_index, &if_unique_name,
     143          31 :                            &var_unique, &not_in_string_table, &call_runtime);
     144             : 
     145          31 :       BIND(&not_in_string_table);
     146             :       {
     147             :         // If the string was not found in the string table, then no regular
     148             :         // object can have a property with that name, so return |false|.
     149             :         // "Special API objects" with interceptors must take the slow path.
     150             :         Branch(IsSpecialReceiverInstanceType(instance_type), &call_runtime,
     151          62 :                &return_false);
     152          31 :       }
     153          31 :     }
     154             :   }
     155          31 :   BIND(&to_primitive);
     156          62 :   GotoIf(IsNumber(key), &return_false);
     157          62 :   Branch(IsName(key), &return_false, &call_runtime);
     158             : 
     159          31 :   BIND(&return_true);
     160          62 :   Return(BooleanConstant(true));
     161             : 
     162          31 :   BIND(&return_false);
     163          62 :   Return(BooleanConstant(false));
     164             : 
     165          31 :   BIND(&call_runtime);
     166          62 :   Return(CallRuntime(Runtime::kObjectHasOwnProperty, context, object, key));
     167          31 : }
     168             : 
     169             : // ES #sec-object.keys
     170         124 : TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) {
     171             :   Node* object = Parameter(Descriptor::kObject);
     172             :   Node* context = Parameter(Descriptor::kContext);
     173             : 
     174          31 :   VARIABLE(var_length, MachineRepresentation::kTagged);
     175          62 :   VARIABLE(var_elements, MachineRepresentation::kTagged);
     176          31 :   Label if_empty(this, Label::kDeferred), if_empty_elements(this),
     177          31 :       if_fast(this), if_slow(this, Label::kDeferred), if_join(this);
     178             : 
     179             :   // Check if the {object} has a usable enum cache.
     180          62 :   GotoIf(TaggedIsSmi(object), &if_slow);
     181          62 :   Node* object_map = LoadMap(object);
     182          62 :   Node* object_bit_field3 = LoadMapBitField3(object_map);
     183             :   Node* object_enum_length =
     184          31 :       DecodeWordFromWord32<Map::EnumLengthBits>(object_bit_field3);
     185             :   GotoIf(
     186          62 :       WordEqual(object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel)),
     187          62 :       &if_slow);
     188             : 
     189             :   // Ensure that the {object} doesn't have any elements.
     190             :   CSA_ASSERT(this, IsJSObjectMap(object_map));
     191          62 :   Node* object_elements = LoadElements(object);
     192          62 :   GotoIf(IsEmptyFixedArray(object_elements), &if_empty_elements);
     193          31 :   Branch(IsEmptySlowElementDictionary(object_elements), &if_empty_elements,
     194          62 :          &if_slow);
     195             : 
     196             :   // Check whether there are enumerable properties.
     197          31 :   BIND(&if_empty_elements);
     198          93 :   Branch(WordEqual(object_enum_length, IntPtrConstant(0)), &if_empty, &if_fast);
     199             : 
     200          31 :   BIND(&if_fast);
     201             :   {
     202             :     // The {object} has a usable enum cache, use that.
     203          62 :     Node* object_descriptors = LoadMapDescriptors(object_map);
     204             :     Node* object_enum_cache =
     205             :         LoadObjectField(object_descriptors, DescriptorArray::kEnumCacheOffset);
     206             :     Node* object_enum_keys =
     207             :         LoadObjectField(object_enum_cache, EnumCache::kKeysOffset);
     208             : 
     209             :     // Allocate a JSArray and copy the elements from the {object_enum_keys}.
     210          31 :     Node* array = nullptr;
     211          31 :     Node* elements = nullptr;
     212          62 :     Node* native_context = LoadNativeContext(context);
     213          62 :     Node* array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
     214          62 :     Node* array_length = SmiTag(object_enum_length);
     215          62 :     std::tie(array, elements) = AllocateUninitializedJSArrayWithElements(
     216             :         PACKED_ELEMENTS, array_map, array_length, nullptr, object_enum_length,
     217             :         INTPTR_PARAMETERS);
     218             :     CopyFixedArrayElements(PACKED_ELEMENTS, object_enum_keys, elements,
     219          31 :                            object_enum_length, SKIP_WRITE_BARRIER);
     220          31 :     Return(array);
     221             :   }
     222             : 
     223          31 :   BIND(&if_empty);
     224             :   {
     225             :     // The {object} doesn't have any enumerable keys.
     226          62 :     var_length.Bind(SmiConstant(0));
     227          62 :     var_elements.Bind(EmptyFixedArrayConstant());
     228          31 :     Goto(&if_join);
     229             :   }
     230             : 
     231          31 :   BIND(&if_slow);
     232             :   {
     233             :     // Let the runtime compute the elements.
     234             :     Node* elements = CallRuntime(Runtime::kObjectKeys, context, object);
     235          31 :     var_length.Bind(LoadObjectField(elements, FixedArray::kLengthOffset));
     236          31 :     var_elements.Bind(elements);
     237          31 :     Goto(&if_join);
     238             :   }
     239             : 
     240          31 :   BIND(&if_join);
     241             :   {
     242             :     // Wrap the elements into a proper JSArray and return that.
     243          62 :     Node* native_context = LoadNativeContext(context);
     244          62 :     Node* array_map = LoadJSArrayElementsMap(PACKED_ELEMENTS, native_context);
     245             :     Node* array = AllocateUninitializedJSArrayWithoutElements(
     246          31 :         array_map, var_length.value(), nullptr);
     247             :     StoreObjectFieldNoWriteBarrier(array, JSArray::kElementsOffset,
     248          31 :                                    var_elements.value());
     249          31 :     Return(array);
     250          31 :   }
     251          31 : }
     252             : 
     253             : // ES #sec-object.prototype.isprototypeof
     254         124 : TF_BUILTIN(ObjectPrototypeIsPrototypeOf, ObjectBuiltinsAssembler) {
     255             :   Node* receiver = Parameter(Descriptor::kReceiver);
     256             :   Node* value = Parameter(Descriptor::kValue);
     257             :   Node* context = Parameter(Descriptor::kContext);
     258             :   Label if_receiverisnullorundefined(this, Label::kDeferred),
     259          31 :       if_valueisnotreceiver(this, Label::kDeferred);
     260             : 
     261             :   // We only check whether {value} is a Smi here, so that the
     262             :   // prototype chain walk below can safely access the {value}s
     263             :   // map. We don't rule out Primitive {value}s, since all of
     264             :   // them have null as their prototype, so the chain walk below
     265             :   // immediately aborts and returns false anyways.
     266          62 :   GotoIf(TaggedIsSmi(value), &if_valueisnotreceiver);
     267             : 
     268             :   // Check if {receiver} is either null or undefined and in that case,
     269             :   // invoke the ToObject builtin, which raises the appropriate error.
     270             :   // Otherwise we don't need to invoke ToObject, since {receiver} is
     271             :   // either already a JSReceiver, in which case ToObject is a no-op,
     272             :   // or it's a Primitive and ToObject would allocate a fresh JSValue
     273             :   // wrapper, which wouldn't be identical to any existing JSReceiver
     274             :   // found in the prototype chain of {value}, hence it will return
     275             :   // false no matter if we search for the Primitive {receiver} or
     276             :   // a newly allocated JSValue wrapper for {receiver}.
     277          62 :   GotoIf(IsNull(receiver), &if_receiverisnullorundefined);
     278          62 :   GotoIf(IsUndefined(receiver), &if_receiverisnullorundefined);
     279             : 
     280             :   // Loop through the prototype chain looking for the {receiver}.
     281          62 :   Return(HasInPrototypeChain(context, value, receiver));
     282             : 
     283          31 :   BIND(&if_receiverisnullorundefined);
     284             :   {
     285             :     // If {value} is a primitive HeapObject, we need to return
     286             :     // false instead of throwing an exception per order of the
     287             :     // steps in the specification, so check that first here.
     288          62 :     GotoIfNot(IsJSReceiver(value), &if_valueisnotreceiver);
     289             : 
     290             :     // Simulate the ToObject invocation on {receiver}.
     291          31 :     CallBuiltin(Builtins::kToObject, context, receiver);
     292          31 :     Unreachable();
     293             :   }
     294             : 
     295          31 :   BIND(&if_valueisnotreceiver);
     296          93 :   Return(FalseConstant());
     297          31 : }
     298             : 
     299             : // ES #sec-object.prototype.tostring
     300         155 : TF_BUILTIN(ObjectPrototypeToString, ObjectBuiltinsAssembler) {
     301          62 :   Label checkstringtag(this), if_apiobject(this, Label::kDeferred),
     302          31 :       if_arguments(this), if_array(this), if_boolean(this), if_date(this),
     303          31 :       if_error(this), if_function(this), if_number(this, Label::kDeferred),
     304          31 :       if_object(this), if_primitive(this), if_proxy(this, Label::kDeferred),
     305          31 :       if_regexp(this), if_string(this), if_symbol(this, Label::kDeferred),
     306          31 :       if_value(this);
     307             : 
     308             :   Node* receiver = Parameter(Descriptor::kReceiver);
     309             :   Node* context = Parameter(Descriptor::kContext);
     310             : 
     311             :   // This is arranged to check the likely cases first.
     312          62 :   VARIABLE(var_default, MachineRepresentation::kTagged);
     313          62 :   VARIABLE(var_holder, MachineRepresentation::kTagged, receiver);
     314          62 :   GotoIf(TaggedIsSmi(receiver), &if_number);
     315          62 :   Node* receiver_map = LoadMap(receiver);
     316          62 :   Node* receiver_instance_type = LoadMapInstanceType(receiver_map);
     317          62 :   GotoIf(IsPrimitiveInstanceType(receiver_instance_type), &if_primitive);
     318             :   const struct {
     319             :     InstanceType value;
     320             :     Label* label;
     321             :   } kJumpTable[] = {{JS_OBJECT_TYPE, &if_object},
     322             :                     {JS_ARRAY_TYPE, &if_array},
     323             :                     {JS_FUNCTION_TYPE, &if_function},
     324             :                     {JS_REGEXP_TYPE, &if_regexp},
     325             :                     {JS_ARGUMENTS_TYPE, &if_arguments},
     326             :                     {JS_DATE_TYPE, &if_date},
     327             :                     {JS_BOUND_FUNCTION_TYPE, &if_function},
     328             :                     {JS_API_OBJECT_TYPE, &if_apiobject},
     329             :                     {JS_SPECIAL_API_OBJECT_TYPE, &if_apiobject},
     330             :                     {JS_PROXY_TYPE, &if_proxy},
     331             :                     {JS_ERROR_TYPE, &if_error},
     332          31 :                     {JS_VALUE_TYPE, &if_value}};
     333             :   size_t const kNumCases = arraysize(kJumpTable);
     334             :   Label* case_labels[kNumCases];
     335             :   int32_t case_values[kNumCases];
     336         403 :   for (size_t i = 0; i < kNumCases; ++i) {
     337         372 :     case_labels[i] = kJumpTable[i].label;
     338         372 :     case_values[i] = kJumpTable[i].value;
     339             :   }
     340             :   Switch(receiver_instance_type, &if_object, case_values, case_labels,
     341          31 :          arraysize(case_values));
     342             : 
     343          31 :   BIND(&if_apiobject);
     344             :   {
     345             :     // Lookup the @@toStringTag property on the {receiver}.
     346          62 :     VARIABLE(var_tag, MachineRepresentation::kTagged,
     347             :              GetProperty(context, receiver,
     348             :                          isolate()->factory()->to_string_tag_symbol()));
     349          31 :     Label if_tagisnotstring(this), if_tagisstring(this);
     350          93 :     GotoIf(TaggedIsSmi(var_tag.value()), &if_tagisnotstring);
     351          62 :     Branch(IsString(var_tag.value()), &if_tagisstring, &if_tagisnotstring);
     352          31 :     BIND(&if_tagisnotstring);
     353             :     {
     354             :       var_tag.Bind(
     355             :           CallStub(Builtins::CallableFor(isolate(), Builtins::kClassOf),
     356          62 :                    context, receiver));
     357          31 :       Goto(&if_tagisstring);
     358             :     }
     359          31 :     BIND(&if_tagisstring);
     360          62 :     ReturnToStringFormat(context, var_tag.value());
     361             :   }
     362             : 
     363          31 :   BIND(&if_arguments);
     364             :   {
     365          62 :     var_default.Bind(LoadRoot(Heap::karguments_to_stringRootIndex));
     366          31 :     Goto(&checkstringtag);
     367             :   }
     368             : 
     369          31 :   BIND(&if_array);
     370             :   {
     371          62 :     var_default.Bind(LoadRoot(Heap::karray_to_stringRootIndex));
     372          31 :     Goto(&checkstringtag);
     373             :   }
     374             : 
     375          31 :   BIND(&if_boolean);
     376             :   {
     377          62 :     Node* native_context = LoadNativeContext(context);
     378             :     Node* boolean_constructor =
     379          62 :         LoadContextElement(native_context, Context::BOOLEAN_FUNCTION_INDEX);
     380             :     Node* boolean_initial_map = LoadObjectField(
     381             :         boolean_constructor, JSFunction::kPrototypeOrInitialMapOffset);
     382             :     Node* boolean_prototype =
     383             :         LoadObjectField(boolean_initial_map, Map::kPrototypeOffset);
     384          62 :     var_default.Bind(LoadRoot(Heap::kboolean_to_stringRootIndex));
     385          31 :     var_holder.Bind(boolean_prototype);
     386          31 :     Goto(&checkstringtag);
     387             :   }
     388             : 
     389          31 :   BIND(&if_date);
     390             :   {
     391          62 :     var_default.Bind(LoadRoot(Heap::kdate_to_stringRootIndex));
     392          31 :     Goto(&checkstringtag);
     393             :   }
     394             : 
     395          31 :   BIND(&if_error);
     396             :   {
     397          62 :     var_default.Bind(LoadRoot(Heap::kerror_to_stringRootIndex));
     398          31 :     Goto(&checkstringtag);
     399             :   }
     400             : 
     401          31 :   BIND(&if_function);
     402             :   {
     403          62 :     var_default.Bind(LoadRoot(Heap::kfunction_to_stringRootIndex));
     404          31 :     Goto(&checkstringtag);
     405             :   }
     406             : 
     407          31 :   BIND(&if_number);
     408             :   {
     409          62 :     Node* native_context = LoadNativeContext(context);
     410             :     Node* number_constructor =
     411          62 :         LoadContextElement(native_context, Context::NUMBER_FUNCTION_INDEX);
     412             :     Node* number_initial_map = LoadObjectField(
     413             :         number_constructor, JSFunction::kPrototypeOrInitialMapOffset);
     414             :     Node* number_prototype =
     415             :         LoadObjectField(number_initial_map, Map::kPrototypeOffset);
     416          62 :     var_default.Bind(LoadRoot(Heap::knumber_to_stringRootIndex));
     417          31 :     var_holder.Bind(number_prototype);
     418          31 :     Goto(&checkstringtag);
     419             :   }
     420             : 
     421          31 :   BIND(&if_object);
     422             :   {
     423             :     CSA_ASSERT(this, IsJSReceiver(receiver));
     424          62 :     var_default.Bind(LoadRoot(Heap::kobject_to_stringRootIndex));
     425          31 :     Goto(&checkstringtag);
     426             :   }
     427             : 
     428          31 :   BIND(&if_primitive);
     429             :   {
     430          31 :     Label return_null(this), return_undefined(this);
     431             : 
     432          62 :     GotoIf(IsStringInstanceType(receiver_instance_type), &if_string);
     433          62 :     GotoIf(IsBooleanMap(receiver_map), &if_boolean);
     434          62 :     GotoIf(IsHeapNumberMap(receiver_map), &if_number);
     435          62 :     GotoIf(IsSymbolMap(receiver_map), &if_symbol);
     436          62 :     Branch(IsUndefined(receiver), &return_undefined, &return_null);
     437             : 
     438          31 :     BIND(&return_undefined);
     439          62 :     Return(LoadRoot(Heap::kundefined_to_stringRootIndex));
     440             : 
     441          31 :     BIND(&return_null);
     442          93 :     Return(LoadRoot(Heap::knull_to_stringRootIndex));
     443             :   }
     444             : 
     445          31 :   BIND(&if_proxy);
     446             :   {
     447             :     // If {receiver} is a proxy for a JSArray, we default to "[object Array]",
     448             :     // otherwise we default to "[object Object]" or "[object Function]" here,
     449             :     // depending on whether the {receiver} is callable. The order matters here,
     450             :     // i.e. we need to execute the %ArrayIsArray check before the [[Get]] below,
     451             :     // as the exception is observable.
     452             :     Node* receiver_is_array =
     453             :         CallRuntime(Runtime::kArrayIsArray, context, receiver);
     454             :     Node* builtin_tag = SelectTaggedConstant<Object>(
     455          31 :         IsTrue(receiver_is_array), LoadRoot(Heap::kArray_stringRootIndex),
     456             :         SelectTaggedConstant<Object>(IsCallableMap(receiver_map),
     457             :                                      LoadRoot(Heap::kFunction_stringRootIndex),
     458         186 :                                      LoadRoot(Heap::kObject_stringRootIndex)));
     459             : 
     460             :     // Lookup the @@toStringTag property on the {receiver}.
     461          62 :     VARIABLE(var_tag, MachineRepresentation::kTagged,
     462             :              GetProperty(context, receiver,
     463             :                          isolate()->factory()->to_string_tag_symbol()));
     464          31 :     Label if_tagisnotstring(this), if_tagisstring(this);
     465          93 :     GotoIf(TaggedIsSmi(var_tag.value()), &if_tagisnotstring);
     466          62 :     Branch(IsString(var_tag.value()), &if_tagisstring, &if_tagisnotstring);
     467          31 :     BIND(&if_tagisnotstring);
     468             :     {
     469          31 :       var_tag.Bind(builtin_tag);
     470          31 :       Goto(&if_tagisstring);
     471             :     }
     472          31 :     BIND(&if_tagisstring);
     473          62 :     ReturnToStringFormat(context, var_tag.value());
     474             :   }
     475             : 
     476          31 :   BIND(&if_regexp);
     477             :   {
     478          62 :     var_default.Bind(LoadRoot(Heap::kregexp_to_stringRootIndex));
     479          31 :     Goto(&checkstringtag);
     480             :   }
     481             : 
     482          31 :   BIND(&if_string);
     483             :   {
     484          62 :     Node* native_context = LoadNativeContext(context);
     485             :     Node* string_constructor =
     486          62 :         LoadContextElement(native_context, Context::STRING_FUNCTION_INDEX);
     487             :     Node* string_initial_map = LoadObjectField(
     488             :         string_constructor, JSFunction::kPrototypeOrInitialMapOffset);
     489             :     Node* string_prototype =
     490             :         LoadObjectField(string_initial_map, Map::kPrototypeOffset);
     491          62 :     var_default.Bind(LoadRoot(Heap::kstring_to_stringRootIndex));
     492          31 :     var_holder.Bind(string_prototype);
     493          31 :     Goto(&checkstringtag);
     494             :   }
     495             : 
     496          31 :   BIND(&if_symbol);
     497             :   {
     498          62 :     Node* native_context = LoadNativeContext(context);
     499             :     Node* symbol_constructor =
     500          62 :         LoadContextElement(native_context, Context::SYMBOL_FUNCTION_INDEX);
     501             :     Node* symbol_initial_map = LoadObjectField(
     502             :         symbol_constructor, JSFunction::kPrototypeOrInitialMapOffset);
     503             :     Node* symbol_prototype =
     504             :         LoadObjectField(symbol_initial_map, Map::kPrototypeOffset);
     505          62 :     var_default.Bind(LoadRoot(Heap::kobject_to_stringRootIndex));
     506          31 :     var_holder.Bind(symbol_prototype);
     507          31 :     Goto(&checkstringtag);
     508             :   }
     509             : 
     510          31 :   BIND(&if_value);
     511             :   {
     512          31 :     Node* receiver_value = LoadJSValueValue(receiver);
     513          62 :     GotoIf(TaggedIsSmi(receiver_value), &if_number);
     514          62 :     Node* receiver_value_map = LoadMap(receiver_value);
     515          62 :     GotoIf(IsHeapNumberMap(receiver_value_map), &if_number);
     516          62 :     GotoIf(IsBooleanMap(receiver_value_map), &if_boolean);
     517          62 :     Branch(IsSymbolMap(receiver_value_map), &if_symbol, &if_string);
     518             :   }
     519             : 
     520          31 :   BIND(&checkstringtag);
     521             :   {
     522             :     // Check if all relevant maps (including the prototype maps) don't
     523             :     // have any interesting symbols (i.e. that none of them have the
     524             :     // @@toStringTag property).
     525          31 :     Label loop(this, &var_holder), return_default(this),
     526          31 :         return_generic(this, Label::kDeferred);
     527          31 :     Goto(&loop);
     528          31 :     BIND(&loop);
     529             :     {
     530          31 :       Node* holder = var_holder.value();
     531          62 :       GotoIf(IsNull(holder), &return_default);
     532          62 :       Node* holder_map = LoadMap(holder);
     533          62 :       Node* holder_bit_field3 = LoadMapBitField3(holder_map);
     534             :       GotoIf(IsSetWord32<Map::MayHaveInterestingSymbols>(holder_bit_field3),
     535          31 :              &return_generic);
     536          62 :       var_holder.Bind(LoadMapPrototype(holder_map));
     537          31 :       Goto(&loop);
     538             :     }
     539             : 
     540          31 :     BIND(&return_generic);
     541             :     {
     542             :       Node* tag = GetProperty(
     543             :           context, CallBuiltin(Builtins::kToObject, context, receiver),
     544          62 :           LoadRoot(Heap::kto_string_tag_symbolRootIndex));
     545          62 :       GotoIf(TaggedIsSmi(tag), &return_default);
     546          62 :       GotoIfNot(IsString(tag), &return_default);
     547          31 :       ReturnToStringFormat(context, tag);
     548             :     }
     549             : 
     550          31 :     BIND(&return_default);
     551          93 :     Return(var_default.value());
     552          31 :   }
     553          31 : }
     554             : 
     555             : // ES6 #sec-object.prototype.valueof
     556          93 : TF_BUILTIN(ObjectPrototypeValueOf, CodeStubAssembler) {
     557             :   Node* receiver = Parameter(Descriptor::kReceiver);
     558             :   Node* context = Parameter(Descriptor::kContext);
     559             : 
     560          62 :   Return(CallBuiltin(Builtins::kToObject, context, receiver));
     561          31 : }
     562             : 
     563             : // ES #sec-object.create
     564         155 : TF_BUILTIN(ObjectCreate, ObjectBuiltinsAssembler) {
     565             :   int const kPrototypeArg = 0;
     566             :   int const kPropertiesArg = 1;
     567             : 
     568             :   Node* argc =
     569          62 :       ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
     570          31 :   CodeStubArguments args(this, argc);
     571             : 
     572          62 :   Node* prototype = args.GetOptionalArgumentValue(kPrototypeArg);
     573          62 :   Node* properties = args.GetOptionalArgumentValue(kPropertiesArg);
     574             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     575             : 
     576          31 :   Label call_runtime(this, Label::kDeferred), prototype_valid(this),
     577          31 :       no_properties(this);
     578             :   {
     579          31 :     Comment("Argument 1 check: prototype");
     580          62 :     GotoIf(WordEqual(prototype, NullConstant()), &prototype_valid);
     581          31 :     BranchIfJSReceiver(prototype, &prototype_valid, &call_runtime);
     582             :   }
     583             : 
     584          31 :   BIND(&prototype_valid);
     585             :   {
     586          31 :     Comment("Argument 2 check: properties");
     587             :     // Check that we have a simple object
     588          62 :     GotoIf(TaggedIsSmi(properties), &call_runtime);
     589             :     // Undefined implies no properties.
     590          62 :     GotoIf(WordEqual(properties, UndefinedConstant()), &no_properties);
     591          62 :     Node* properties_map = LoadMap(properties);
     592          62 :     GotoIf(IsSpecialReceiverMap(properties_map), &call_runtime);
     593             :     // Stay on the fast path only if there are no elements.
     594             :     GotoIfNot(WordEqual(LoadElements(properties),
     595          93 :                         LoadRoot(Heap::kEmptyFixedArrayRootIndex)),
     596          31 :               &call_runtime);
     597             :     // Handle dictionary objects or fast objects with properties in runtime.
     598          62 :     Node* bit_field3 = LoadMapBitField3(properties_map);
     599          31 :     GotoIf(IsSetWord32<Map::DictionaryMap>(bit_field3), &call_runtime);
     600             :     Branch(IsSetWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3),
     601          31 :            &call_runtime, &no_properties);
     602             :   }
     603             : 
     604             :   // Create a new object with the given prototype.
     605          31 :   BIND(&no_properties);
     606             :   {
     607          31 :     VARIABLE(map, MachineRepresentation::kTagged);
     608          62 :     VARIABLE(properties, MachineRepresentation::kTagged);
     609          31 :     Label non_null_proto(this), instantiate_map(this), good(this);
     610             : 
     611          62 :     Branch(WordEqual(prototype, NullConstant()), &good, &non_null_proto);
     612             : 
     613          31 :     BIND(&good);
     614             :     {
     615             :       map.Bind(LoadContextElement(
     616          62 :           context, Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP));
     617          31 :       properties.Bind(AllocateNameDictionary(NameDictionary::kInitialCapacity));
     618          31 :       Goto(&instantiate_map);
     619             :     }
     620             : 
     621          31 :     BIND(&non_null_proto);
     622             :     {
     623          62 :       properties.Bind(EmptyFixedArrayConstant());
     624             :       Node* object_function =
     625          62 :           LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX);
     626             :       Node* object_function_map = LoadObjectField(
     627             :           object_function, JSFunction::kPrototypeOrInitialMapOffset);
     628          31 :       map.Bind(object_function_map);
     629          93 :       GotoIf(WordEqual(prototype, LoadMapPrototype(map.value())),
     630          31 :              &instantiate_map);
     631             :       // Try loading the prototype info.
     632             :       Node* prototype_info =
     633          93 :           LoadMapPrototypeInfo(LoadMap(prototype), &call_runtime);
     634          31 :       Comment("Load ObjectCreateMap from PrototypeInfo");
     635             :       Node* weak_cell =
     636             :           LoadObjectField(prototype_info, PrototypeInfo::kObjectCreateMap);
     637          62 :       GotoIf(WordEqual(weak_cell, UndefinedConstant()), &call_runtime);
     638          31 :       map.Bind(LoadWeakCellValue(weak_cell, &call_runtime));
     639          31 :       Goto(&instantiate_map);
     640             :     }
     641             : 
     642          31 :     BIND(&instantiate_map);
     643             :     {
     644          31 :       Node* instance = AllocateJSObjectFromMap(map.value(), properties.value());
     645          31 :       args.PopAndReturn(instance);
     646          31 :     }
     647             :   }
     648             : 
     649          31 :   BIND(&call_runtime);
     650             :   {
     651             :     Node* result =
     652             :         CallRuntime(Runtime::kObjectCreate, context, prototype, properties);
     653          31 :     args.PopAndReturn(result);
     654          31 :   }
     655          31 : }
     656             : 
     657             : // ES #sec-object.is
     658         124 : TF_BUILTIN(ObjectIs, ObjectBuiltinsAssembler) {
     659             :   Node* const left = Parameter(Descriptor::kLeft);
     660             :   Node* const right = Parameter(Descriptor::kRight);
     661             : 
     662          31 :   Label return_true(this), return_false(this);
     663          31 :   BranchIfSameValue(left, right, &return_true, &return_false);
     664             : 
     665          31 :   BIND(&return_true);
     666          62 :   Return(TrueConstant());
     667             : 
     668          31 :   BIND(&return_false);
     669          93 :   Return(FalseConstant());
     670          31 : }
     671             : 
     672         124 : TF_BUILTIN(CreateIterResultObject, ObjectBuiltinsAssembler) {
     673             :   Node* const value = Parameter(Descriptor::kValue);
     674             :   Node* const done = Parameter(Descriptor::kDone);
     675             :   Node* const context = Parameter(Descriptor::kContext);
     676             : 
     677          62 :   Node* const native_context = LoadNativeContext(context);
     678             :   Node* const map =
     679          62 :       LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
     680             : 
     681          31 :   Node* const result = AllocateJSObjectFromMap(map);
     682             : 
     683          31 :   StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kValueOffset, value);
     684          31 :   StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kDoneOffset, done);
     685             : 
     686          31 :   Return(result);
     687          31 : }
     688             : 
     689         124 : TF_BUILTIN(HasProperty, ObjectBuiltinsAssembler) {
     690             :   Node* key = Parameter(Descriptor::kKey);
     691             :   Node* object = Parameter(Descriptor::kObject);
     692             :   Node* context = Parameter(Descriptor::kContext);
     693             : 
     694          62 :   Return(HasProperty(object, key, context, kHasProperty));
     695          31 : }
     696             : 
     697         124 : TF_BUILTIN(InstanceOf, ObjectBuiltinsAssembler) {
     698             :   Node* object = Parameter(Descriptor::kLeft);
     699             :   Node* callable = Parameter(Descriptor::kRight);
     700             :   Node* context = Parameter(Descriptor::kContext);
     701             : 
     702          62 :   Return(InstanceOf(object, callable, context));
     703          31 : }
     704             : 
     705             : // ES6 section 7.3.19 OrdinaryHasInstance ( C, O )
     706         124 : TF_BUILTIN(OrdinaryHasInstance, ObjectBuiltinsAssembler) {
     707             :   Node* constructor = Parameter(Descriptor::kLeft);
     708             :   Node* object = Parameter(Descriptor::kRight);
     709             :   Node* context = Parameter(Descriptor::kContext);
     710             : 
     711          62 :   Return(OrdinaryHasInstance(context, constructor, object));
     712          31 : }
     713             : 
     714         124 : TF_BUILTIN(GetSuperConstructor, ObjectBuiltinsAssembler) {
     715             :   Node* object = Parameter(Descriptor::kObject);
     716             :   Node* context = Parameter(Descriptor::kContext);
     717             : 
     718          62 :   Return(GetSuperConstructor(object, context));
     719          31 : }
     720             : 
     721         124 : TF_BUILTIN(CreateGeneratorObject, ObjectBuiltinsAssembler) {
     722             :   Node* closure = Parameter(Descriptor::kClosure);
     723             :   Node* receiver = Parameter(Descriptor::kReceiver);
     724             :   Node* context = Parameter(Descriptor::kContext);
     725             : 
     726             :   // Get the initial map from the function, jumping to the runtime if we don't
     727             :   // have one.
     728             :   Label runtime(this);
     729          93 :   GotoIfNot(IsFunctionWithPrototypeSlotMap(LoadMap(closure)), &runtime);
     730             :   Node* maybe_map =
     731             :       LoadObjectField(closure, JSFunction::kPrototypeOrInitialMapOffset);
     732          62 :   GotoIf(DoesntHaveInstanceType(maybe_map, MAP_TYPE), &runtime);
     733             : 
     734             :   Node* shared =
     735             :       LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset);
     736             :   Node* bytecode_array =
     737             :       LoadObjectField(shared, SharedFunctionInfo::kFunctionDataOffset);
     738             :   Node* frame_size = ChangeInt32ToIntPtr(LoadObjectField(
     739          93 :       bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Int32()));
     740          93 :   Node* size = WordSar(frame_size, IntPtrConstant(kPointerSizeLog2));
     741          31 :   Node* register_file = AllocateFixedArray(HOLEY_ELEMENTS, size);
     742             :   FillFixedArrayWithValue(HOLEY_ELEMENTS, register_file, IntPtrConstant(0),
     743          62 :                           size, Heap::kUndefinedValueRootIndex);
     744             : 
     745          31 :   Node* const result = AllocateJSObjectFromMap(maybe_map);
     746             : 
     747             :   StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kFunctionOffset,
     748          31 :                                  closure);
     749             :   StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kContextOffset,
     750          31 :                                  context);
     751             :   StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kReceiverOffset,
     752          31 :                                  receiver);
     753             :   StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kRegisterFileOffset,
     754          31 :                                  register_file);
     755          62 :   Node* executing = SmiConstant(JSGeneratorObject::kGeneratorExecuting);
     756             :   StoreObjectFieldNoWriteBarrier(result, JSGeneratorObject::kContinuationOffset,
     757          31 :                                  executing);
     758          31 :   HandleSlackTracking(context, result, maybe_map, JSGeneratorObject::kSize);
     759          31 :   Return(result);
     760             : 
     761          31 :   BIND(&runtime);
     762             :   {
     763             :     Return(CallRuntime(Runtime::kCreateJSGeneratorObject, context, closure,
     764          31 :                        receiver));
     765          31 :   }
     766          31 : }
     767             : 
     768             : // ES6 section 19.1.2.7 Object.getOwnPropertyDescriptor ( O, P )
     769         124 : TF_BUILTIN(ObjectGetOwnPropertyDescriptor, ObjectBuiltinsAssembler) {
     770             :   Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
     771             :   Node* context = Parameter(BuiltinDescriptor::kContext);
     772             :   CSA_ASSERT(this, WordEqual(Parameter(BuiltinDescriptor::kNewTarget),
     773             :                              UndefinedConstant()));
     774             : 
     775          93 :   CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
     776          62 :   Node* object = args.GetOptionalArgumentValue(0);
     777          62 :   Node* key = args.GetOptionalArgumentValue(1);
     778             : 
     779             :   // 1. Let obj be ? ToObject(O).
     780          31 :   object = CallBuiltin(Builtins::kToObject, context, object);
     781             : 
     782             :   // 2. Let key be ? ToPropertyKey(P).
     783          31 :   key = ToName(context, key);
     784             : 
     785             :   // 3. Let desc be ? obj.[[GetOwnProperty]](key).
     786          31 :   Label if_keyisindex(this), if_iskeyunique(this),
     787          31 :       call_runtime(this, Label::kDeferred),
     788          31 :       return_undefined(this, Label::kDeferred), if_notunique_name(this);
     789          62 :   Node* map = LoadMap(object);
     790          62 :   Node* instance_type = LoadMapInstanceType(map);
     791             :   GotoIf(Int32LessThanOrEqual(instance_type,
     792          62 :                               Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
     793          62 :          &call_runtime);
     794             :   {
     795          62 :     VARIABLE(var_index, MachineType::PointerRepresentation(),
     796             :              IntPtrConstant(0));
     797          62 :     VARIABLE(var_name, MachineRepresentation::kTagged);
     798             : 
     799             :     TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, &var_name,
     800          31 :               &call_runtime, &if_notunique_name);
     801             : 
     802          31 :     BIND(&if_notunique_name);
     803             :     {
     804             :       Label not_in_string_table(this);
     805             :       TryInternalizeString(key, &if_keyisindex, &var_index, &if_iskeyunique,
     806          31 :                            &var_name, &not_in_string_table, &call_runtime);
     807             : 
     808          31 :       BIND(&not_in_string_table);
     809             :       {
     810             :         // If the string was not found in the string table, then no regular
     811             :         // object can have a property with that name, so return |undefined|.
     812          31 :         Goto(&return_undefined);
     813          31 :       }
     814             :     }
     815             : 
     816          31 :     BIND(&if_iskeyunique);
     817             :     {
     818          31 :       Label if_found_value(this), return_empty(this), if_not_found(this);
     819             : 
     820          62 :       VARIABLE(var_value, MachineRepresentation::kTagged);
     821          62 :       VARIABLE(var_details, MachineRepresentation::kWord32);
     822          62 :       VARIABLE(var_raw_value, MachineRepresentation::kTagged);
     823             : 
     824             :       TryGetOwnProperty(context, object, object, map, instance_type,
     825             :                         var_name.value(), &if_found_value, &var_value,
     826             :                         &var_details, &var_raw_value, &return_empty,
     827          31 :                         &if_not_found, kReturnAccessorPair);
     828             : 
     829          31 :       BIND(&if_found_value);
     830             :       // 4. Return FromPropertyDescriptor(desc).
     831             :       Node* js_desc = FromPropertyDetails(context, var_value.value(),
     832          31 :                                           var_details.value(), &call_runtime);
     833          31 :       args.PopAndReturn(js_desc);
     834             : 
     835          31 :       BIND(&return_empty);
     836          62 :       var_value.Bind(UndefinedConstant());
     837          62 :       args.PopAndReturn(UndefinedConstant());
     838             : 
     839          31 :       BIND(&if_not_found);
     840          62 :       Goto(&call_runtime);
     841          31 :     }
     842             :   }
     843             : 
     844          31 :   BIND(&if_keyisindex);
     845          31 :   Goto(&call_runtime);
     846             : 
     847          31 :   BIND(&call_runtime);
     848             :   {
     849             :     Node* desc =
     850             :         CallRuntime(Runtime::kGetOwnPropertyDescriptor, context, object, key);
     851             : 
     852          62 :     GotoIf(IsUndefined(desc), &return_undefined);
     853             : 
     854             :     CSA_ASSERT(this, IsFixedArray(desc));
     855             : 
     856             :     // 4. Return FromPropertyDescriptor(desc).
     857          31 :     Node* js_desc = FromPropertyDescriptor(context, desc);
     858          31 :     args.PopAndReturn(js_desc);
     859             :   }
     860          31 :   BIND(&return_undefined);
     861          93 :   args.PopAndReturn(UndefinedConstant());
     862          31 : }
     863             : 
     864         186 : void ObjectBuiltinsAssembler::AddToDictionaryIf(Node* condition,
     865             :                                                 Node* name_dictionary,
     866             :                                                 Handle<Name> name, Node* value,
     867             :                                                 Label* bailout) {
     868         186 :   Label done(this);
     869         186 :   GotoIfNot(condition, &done);
     870             : 
     871         186 :   Add<NameDictionary>(name_dictionary, HeapConstant(name), value, bailout);
     872         186 :   Goto(&done);
     873             : 
     874         186 :   BIND(&done);
     875         186 : }
     876             : 
     877          31 : Node* ObjectBuiltinsAssembler::FromPropertyDescriptor(Node* context,
     878             :                                                       Node* desc) {
     879          31 :   VARIABLE(js_descriptor, MachineRepresentation::kTagged);
     880             : 
     881             :   Node* flags = LoadAndUntagToWord32ObjectField(
     882          62 :       desc, PropertyDescriptorObject::kFlagsOffset);
     883             : 
     884             :   Node* has_flags =
     885          93 :       Word32And(flags, Int32Constant(PropertyDescriptorObject::kHasMask));
     886             : 
     887          31 :   Label if_accessor_desc(this), if_data_desc(this), if_generic_desc(this),
     888          31 :       return_desc(this);
     889             :   GotoIf(
     890             :       Word32Equal(has_flags,
     891             :                   Int32Constant(
     892          62 :                       PropertyDescriptorObject::kRegularAccessorPropertyBits)),
     893          62 :       &if_accessor_desc);
     894             :   GotoIf(Word32Equal(
     895             :              has_flags,
     896          62 :              Int32Constant(PropertyDescriptorObject::kRegularDataPropertyBits)),
     897          62 :          &if_data_desc);
     898          31 :   Goto(&if_generic_desc);
     899             : 
     900          31 :   BIND(&if_accessor_desc);
     901             :   {
     902             :     js_descriptor.Bind(ConstructAccessorDescriptor(
     903             :         context, LoadObjectField(desc, PropertyDescriptorObject::kGetOffset),
     904             :         LoadObjectField(desc, PropertyDescriptorObject::kSetOffset),
     905             :         IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags),
     906          31 :         IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)));
     907          31 :     Goto(&return_desc);
     908             :   }
     909             : 
     910          31 :   BIND(&if_data_desc);
     911             :   {
     912             :     js_descriptor.Bind(ConstructDataDescriptor(
     913             :         context, LoadObjectField(desc, PropertyDescriptorObject::kValueOffset),
     914             :         IsSetWord32<PropertyDescriptorObject::IsWritableBit>(flags),
     915             :         IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags),
     916          31 :         IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)));
     917          31 :     Goto(&return_desc);
     918             :   }
     919             : 
     920          31 :   BIND(&if_generic_desc);
     921             :   {
     922          62 :     Node* native_context = LoadNativeContext(context);
     923             :     Node* map = LoadContextElement(
     924          62 :         native_context, Context::SLOW_OBJECT_WITH_OBJECT_PROTOTYPE_MAP);
     925             :     // We want to preallocate the slots for value, writable, get, set,
     926             :     // enumerable and configurable - a total of 6
     927          31 :     Node* properties = AllocateNameDictionary(6);
     928          31 :     Node* js_desc = AllocateJSObjectFromMap(map, properties);
     929             : 
     930             :     Label bailout(this, Label::kDeferred);
     931             : 
     932          31 :     Factory* factory = isolate()->factory();
     933             :     Node* value = LoadObjectField(desc, PropertyDescriptorObject::kValueOffset);
     934             :     AddToDictionaryIf(IsNotTheHole(value), properties, factory->value_string(),
     935          31 :                       value, &bailout);
     936             :     AddToDictionaryIf(
     937             :         IsSetWord32<PropertyDescriptorObject::HasWritableBit>(flags),
     938             :         properties, factory->writable_string(),
     939             :         SelectBooleanConstant(
     940             :             IsSetWord32<PropertyDescriptorObject::IsWritableBit>(flags)),
     941          62 :         &bailout);
     942             : 
     943             :     Node* get = LoadObjectField(desc, PropertyDescriptorObject::kGetOffset);
     944             :     AddToDictionaryIf(IsNotTheHole(get), properties, factory->get_string(), get,
     945          31 :                       &bailout);
     946             :     Node* set = LoadObjectField(desc, PropertyDescriptorObject::kSetOffset);
     947             :     AddToDictionaryIf(IsNotTheHole(set), properties, factory->set_string(), set,
     948          31 :                       &bailout);
     949             : 
     950             :     AddToDictionaryIf(
     951             :         IsSetWord32<PropertyDescriptorObject::HasEnumerableBit>(flags),
     952             :         properties, factory->enumerable_string(),
     953             :         SelectBooleanConstant(
     954             :             IsSetWord32<PropertyDescriptorObject::IsEnumerableBit>(flags)),
     955          62 :         &bailout);
     956             :     AddToDictionaryIf(
     957             :         IsSetWord32<PropertyDescriptorObject::HasConfigurableBit>(flags),
     958             :         properties, factory->configurable_string(),
     959             :         SelectBooleanConstant(
     960             :             IsSetWord32<PropertyDescriptorObject::IsConfigurableBit>(flags)),
     961          62 :         &bailout);
     962             : 
     963          31 :     js_descriptor.Bind(js_desc);
     964          31 :     Goto(&return_desc);
     965             : 
     966          31 :     BIND(&bailout);
     967             :     CSA_ASSERT(this, Int32Constant(0));
     968          31 :     Unreachable();
     969             :   }
     970             : 
     971          31 :   BIND(&return_desc);
     972          62 :   return js_descriptor.value();
     973             : }
     974             : 
     975          31 : Node* ObjectBuiltinsAssembler::FromPropertyDetails(Node* context,
     976             :                                                    Node* raw_value,
     977             :                                                    Node* details,
     978             :                                                    Label* if_bailout) {
     979          31 :   VARIABLE(js_descriptor, MachineRepresentation::kTagged);
     980             : 
     981          31 :   Label if_accessor_desc(this), if_data_desc(this), return_desc(this);
     982          31 :   BranchIfAccessorPair(raw_value, &if_accessor_desc, &if_data_desc);
     983             : 
     984          31 :   BIND(&if_accessor_desc);
     985             :   {
     986             :     Node* getter = LoadObjectField(raw_value, AccessorPair::kGetterOffset);
     987             :     Node* setter = LoadObjectField(raw_value, AccessorPair::kSetterOffset);
     988             :     js_descriptor.Bind(ConstructAccessorDescriptor(
     989             :         context, GetAccessorOrUndefined(getter, if_bailout),
     990             :         GetAccessorOrUndefined(setter, if_bailout),
     991          31 :         IsNotSetWord32(details, PropertyDetails::kAttributesDontEnumMask),
     992         124 :         IsNotSetWord32(details, PropertyDetails::kAttributesDontDeleteMask)));
     993          31 :     Goto(&return_desc);
     994             :   }
     995             : 
     996          31 :   BIND(&if_data_desc);
     997             :   {
     998             :     js_descriptor.Bind(ConstructDataDescriptor(
     999             :         context, raw_value,
    1000          31 :         IsNotSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
    1001          31 :         IsNotSetWord32(details, PropertyDetails::kAttributesDontEnumMask),
    1002         186 :         IsNotSetWord32(details, PropertyDetails::kAttributesDontDeleteMask)));
    1003          31 :     Goto(&return_desc);
    1004             :   }
    1005             : 
    1006          31 :   BIND(&return_desc);
    1007          62 :   return js_descriptor.value();
    1008             : }
    1009             : 
    1010          62 : Node* ObjectBuiltinsAssembler::GetAccessorOrUndefined(Node* accessor,
    1011             :                                                       Label* if_bailout) {
    1012         124 :   Label bind_undefined(this, Label::kDeferred), return_result(this);
    1013         124 :   VARIABLE(result, MachineRepresentation::kTagged);
    1014             : 
    1015         124 :   GotoIf(IsNull(accessor), &bind_undefined);
    1016          62 :   result.Bind(accessor);
    1017         124 :   Node* map = LoadMap(accessor);
    1018             :   // TODO(ishell): probe template instantiations cache.
    1019         124 :   GotoIf(IsFunctionTemplateInfoMap(map), if_bailout);
    1020          62 :   Goto(&return_result);
    1021             : 
    1022          62 :   BIND(&bind_undefined);
    1023         124 :   result.Bind(UndefinedConstant());
    1024          62 :   Goto(&return_result);
    1025             : 
    1026          62 :   BIND(&return_result);
    1027         124 :   return result.value();
    1028             : }
    1029             : }  // namespace internal
    1030             : }  // namespace v8

Generated by: LCOV version 1.10