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 |