| OLD | NEW | 
|    1 // Copyright 2017 the V8 project authors. All rights reserved. |    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 |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "src/builtins/builtins-utils-gen.h" |    5 #include "src/builtins/builtins-utils-gen.h" | 
|    6 #include "src/builtins/builtins.h" |    6 #include "src/builtins/builtins.h" | 
|    7 #include "src/code-stub-assembler.h" |    7 #include "src/code-stub-assembler.h" | 
|    8  |    8  | 
|    9 namespace v8 { |    9 namespace v8 { | 
|   10 namespace internal { |   10 namespace internal { | 
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   97   BIND(&return_true); |   97   BIND(&return_true); | 
|   98   Return(BooleanConstant(true)); |   98   Return(BooleanConstant(true)); | 
|   99  |   99  | 
|  100   BIND(&return_false); |  100   BIND(&return_false); | 
|  101   Return(BooleanConstant(false)); |  101   Return(BooleanConstant(false)); | 
|  102  |  102  | 
|  103   BIND(&call_runtime); |  103   BIND(&call_runtime); | 
|  104   Return(CallRuntime(Runtime::kObjectHasOwnProperty, context, object, key)); |  104   Return(CallRuntime(Runtime::kObjectHasOwnProperty, context, object, key)); | 
|  105 } |  105 } | 
|  106  |  106  | 
 |  107 // ES #sec-object.keys | 
 |  108 TF_BUILTIN(ObjectKeys, ObjectBuiltinsAssembler) { | 
 |  109   Node* object = Parameter(Descriptor::kObject); | 
 |  110   Node* context = Parameter(Descriptor::kContext); | 
 |  111  | 
 |  112   VARIABLE(var_length, MachineRepresentation::kTagged); | 
 |  113   VARIABLE(var_elements, MachineRepresentation::kTagged); | 
 |  114   Label if_empty(this, Label::kDeferred), if_fast(this), | 
 |  115       if_slow(this, Label::kDeferred), if_join(this); | 
 |  116  | 
 |  117   // Check if the {object} has a usable enum cache. | 
 |  118   GotoIf(TaggedIsSmi(object), &if_slow); | 
 |  119   Node* object_map = LoadMap(object); | 
 |  120   Node* object_bit_field3 = LoadMapBitField3(object_map); | 
 |  121   Node* object_enum_length = | 
 |  122       DecodeWordFromWord32<Map::EnumLengthBits>(object_bit_field3); | 
 |  123   GotoIf( | 
 |  124       WordEqual(object_enum_length, IntPtrConstant(kInvalidEnumCacheSentinel)), | 
 |  125       &if_slow); | 
 |  126  | 
 |  127   // Ensure that the {object} doesn't have any elements. | 
 |  128   CSA_ASSERT(this, IsJSObjectMap(object_map)); | 
 |  129   Node* object_elements = LoadObjectField(object, JSObject::kElementsOffset); | 
 |  130   GotoIfNot(IsEmptyFixedArray(object_elements), &if_slow); | 
 |  131   Branch(WordEqual(object_enum_length, IntPtrConstant(0)), &if_empty, &if_fast); | 
 |  132  | 
 |  133   BIND(&if_fast); | 
 |  134   { | 
 |  135     // The {object} has a usable enum cache, use that. | 
 |  136     Node* object_descriptors = LoadMapDescriptors(object_map); | 
 |  137     Node* object_enum_cache_bridge = LoadObjectField( | 
 |  138         object_descriptors, DescriptorArray::kEnumCacheBridgeOffset); | 
 |  139     Node* object_enum_cache = LoadObjectField( | 
 |  140         object_enum_cache_bridge, DescriptorArray::kEnumCacheBridgeCacheOffset); | 
 |  141  | 
 |  142     // Allocate a JSArray and copy the elements from the {object_enum_cache}. | 
 |  143     Node* array = nullptr; | 
 |  144     Node* elements = nullptr; | 
 |  145     Node* native_context = LoadNativeContext(context); | 
 |  146     Node* array_map = LoadJSArrayElementsMap(FAST_ELEMENTS, native_context); | 
 |  147     Node* array_length = SmiTag(object_enum_length); | 
 |  148     std::tie(array, elements) = AllocateUninitializedJSArrayWithElements( | 
 |  149         FAST_ELEMENTS, array_map, array_length, nullptr, object_enum_length, | 
 |  150         INTPTR_PARAMETERS); | 
 |  151     StoreMapNoWriteBarrier(elements, Heap::kFixedArrayMapRootIndex); | 
 |  152     StoreObjectFieldNoWriteBarrier(elements, FixedArray::kLengthOffset, | 
 |  153                                    array_length); | 
 |  154     CopyFixedArrayElements(FAST_ELEMENTS, object_enum_cache, elements, | 
 |  155                            object_enum_length, SKIP_WRITE_BARRIER); | 
 |  156     Return(array); | 
 |  157   } | 
 |  158  | 
 |  159   BIND(&if_empty); | 
 |  160   { | 
 |  161     // The {object} doesn't have any enumerable keys. | 
 |  162     var_length.Bind(SmiConstant(0)); | 
 |  163     var_elements.Bind(EmptyFixedArrayConstant()); | 
 |  164     Goto(&if_join); | 
 |  165   } | 
 |  166  | 
 |  167   BIND(&if_slow); | 
 |  168   { | 
 |  169     // Let the runtime compute the elements. | 
 |  170     Node* elements = CallRuntime(Runtime::kObjectKeys, context, object); | 
 |  171     var_length.Bind(LoadObjectField(elements, FixedArray::kLengthOffset)); | 
 |  172     var_elements.Bind(elements); | 
 |  173     Goto(&if_join); | 
 |  174   } | 
 |  175  | 
 |  176   BIND(&if_join); | 
 |  177   { | 
 |  178     // Wrap the elements into a proper JSArray and return that. | 
 |  179     Node* native_context = LoadNativeContext(context); | 
 |  180     Node* array_map = LoadJSArrayElementsMap(FAST_ELEMENTS, native_context); | 
 |  181     Node* array = AllocateUninitializedJSArrayWithoutElements( | 
 |  182         FAST_ELEMENTS, array_map, var_length.value(), nullptr); | 
 |  183     StoreObjectFieldNoWriteBarrier(array, JSArray::kElementsOffset, | 
 |  184                                    var_elements.value()); | 
 |  185     Return(array); | 
 |  186   } | 
 |  187 } | 
 |  188  | 
|  107 // ES6 #sec-object.prototype.tostring |  189 // ES6 #sec-object.prototype.tostring | 
|  108 TF_BUILTIN(ObjectProtoToString, ObjectBuiltinsAssembler) { |  190 TF_BUILTIN(ObjectProtoToString, ObjectBuiltinsAssembler) { | 
|  109   Label return_undefined(this, Label::kDeferred), |  191   Label return_undefined(this, Label::kDeferred), | 
|  110       return_null(this, Label::kDeferred), |  192       return_null(this, Label::kDeferred), | 
|  111       return_arguments(this, Label::kDeferred), return_array(this), |  193       return_arguments(this, Label::kDeferred), return_array(this), | 
|  112       return_api(this, Label::kDeferred), return_object(this), |  194       return_api(this, Label::kDeferred), return_object(this), | 
|  113       return_regexp(this), return_function(this), return_error(this), |  195       return_regexp(this), return_function(this), return_error(this), | 
|  114       return_date(this), return_jsvalue(this), |  196       return_date(this), return_jsvalue(this), | 
|  115       return_jsproxy(this, Label::kDeferred); |  197       return_jsproxy(this, Label::kDeferred); | 
|  116  |  198  | 
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  453  |  535  | 
|  454   BIND(&runtime); |  536   BIND(&runtime); | 
|  455   { |  537   { | 
|  456     Return(CallRuntime(Runtime::kCreateJSGeneratorObject, context, closure, |  538     Return(CallRuntime(Runtime::kCreateJSGeneratorObject, context, closure, | 
|  457                        receiver)); |  539                        receiver)); | 
|  458   } |  540   } | 
|  459 } |  541 } | 
|  460  |  542  | 
|  461 }  // namespace internal |  543 }  // namespace internal | 
|  462 }  // namespace v8 |  544 }  // namespace v8 | 
| OLD | NEW |