OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 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 | 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-constructor.h" | 5 #include "src/builtins/builtins-constructor.h" |
6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
7 #include "src/builtins/builtins.h" | 7 #include "src/builtins/builtins.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/code-stub-assembler.h" | 9 #include "src/code-stub-assembler.h" |
10 #include "src/interface-descriptors.h" | 10 #include "src/interface-descriptors.h" |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 | 147 |
148 return result; | 148 return result; |
149 } | 149 } |
150 | 150 |
151 TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) { | 151 TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) { |
152 Node* shared = Parameter(FastNewClosureDescriptor::kSharedFunctionInfo); | 152 Node* shared = Parameter(FastNewClosureDescriptor::kSharedFunctionInfo); |
153 Node* context = Parameter(FastNewClosureDescriptor::kContext); | 153 Node* context = Parameter(FastNewClosureDescriptor::kContext); |
154 Return(EmitFastNewClosure(shared, context)); | 154 Return(EmitFastNewClosure(shared, context)); |
155 } | 155 } |
156 | 156 |
| 157 TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) { |
| 158 typedef FastNewObjectDescriptor Descriptor; |
| 159 Node* context = Parameter(Descriptor::kContext); |
| 160 Node* target = Parameter(Descriptor::kTarget); |
| 161 Node* new_target = Parameter(Descriptor::kNewTarget); |
| 162 |
| 163 CSA_ASSERT(this, HasInstanceType(target, JS_FUNCTION_TYPE)); |
| 164 CSA_ASSERT(this, IsJSReceiver(new_target)); |
| 165 |
| 166 // Verify that the new target is a JSFunction. |
| 167 Label runtime(this), fast(this); |
| 168 GotoIf(HasInstanceType(new_target, JS_FUNCTION_TYPE), &fast); |
| 169 Goto(&runtime); |
| 170 |
| 171 Bind(&runtime); |
| 172 TailCallRuntime(Runtime::kNewObject, context, target, new_target); |
| 173 |
| 174 Bind(&fast); |
| 175 |
| 176 // Load the initial map and verify that it's in fact a map. |
| 177 Node* initial_map = |
| 178 LoadObjectField(new_target, JSFunction::kPrototypeOrInitialMapOffset); |
| 179 GotoIf(TaggedIsSmi(initial_map), &runtime); |
| 180 GotoIf(DoesntHaveInstanceType(initial_map, MAP_TYPE), &runtime); |
| 181 |
| 182 // Fall back to runtime if the target differs from the new target's |
| 183 // initial map constructor. |
| 184 Node* new_target_constructor = |
| 185 LoadObjectField(initial_map, Map::kConstructorOrBackPointerOffset); |
| 186 GotoIf(WordNotEqual(target, new_target_constructor), &runtime); |
| 187 |
| 188 Node* instance_size_words = ChangeUint32ToWord(LoadObjectField( |
| 189 initial_map, Map::kInstanceSizeOffset, MachineType::Uint8())); |
| 190 Node* instance_size = |
| 191 WordShl(instance_size_words, IntPtrConstant(kPointerSizeLog2)); |
| 192 |
| 193 Node* object = Allocate(instance_size); |
| 194 StoreMapNoWriteBarrier(object, initial_map); |
| 195 Node* empty_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex); |
| 196 StoreObjectFieldNoWriteBarrier(object, JSObject::kPropertiesOffset, |
| 197 empty_array); |
| 198 StoreObjectFieldNoWriteBarrier(object, JSObject::kElementsOffset, |
| 199 empty_array); |
| 200 |
| 201 instance_size_words = ChangeUint32ToWord(LoadObjectField( |
| 202 initial_map, Map::kInstanceSizeOffset, MachineType::Uint8())); |
| 203 instance_size = |
| 204 WordShl(instance_size_words, IntPtrConstant(kPointerSizeLog2)); |
| 205 |
| 206 // Perform in-object slack tracking if requested. |
| 207 Node* bit_field3 = LoadMapBitField3(initial_map); |
| 208 Label slack_tracking(this), finalize(this, Label::kDeferred), done(this); |
| 209 GotoIf(IsSetWord32<Map::ConstructionCounter>(bit_field3), &slack_tracking); |
| 210 |
| 211 // Initialize remaining fields. |
| 212 { |
| 213 Comment("no slack tracking"); |
| 214 InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize), |
| 215 instance_size, Heap::kUndefinedValueRootIndex); |
| 216 Return(object); |
| 217 } |
| 218 |
| 219 { |
| 220 Bind(&slack_tracking); |
| 221 |
| 222 // Decrease generous allocation count. |
| 223 STATIC_ASSERT(Map::ConstructionCounter::kNext == 32); |
| 224 Comment("update allocation count"); |
| 225 Node* new_bit_field3 = Int32Sub( |
| 226 bit_field3, Int32Constant(1 << Map::ConstructionCounter::kShift)); |
| 227 StoreObjectFieldNoWriteBarrier(initial_map, Map::kBitField3Offset, |
| 228 new_bit_field3, |
| 229 MachineRepresentation::kWord32); |
| 230 GotoIf(IsClearWord32<Map::ConstructionCounter>(new_bit_field3), &finalize); |
| 231 |
| 232 Node* unused_fields = LoadObjectField( |
| 233 initial_map, Map::kUnusedPropertyFieldsOffset, MachineType::Uint8()); |
| 234 Node* used_size = |
| 235 IntPtrSub(instance_size, WordShl(ChangeUint32ToWord(unused_fields), |
| 236 IntPtrConstant(kPointerSizeLog2))); |
| 237 |
| 238 Comment("initialize filler fields (no finalize)"); |
| 239 InitializeFieldsWithRoot(object, used_size, instance_size, |
| 240 Heap::kOnePointerFillerMapRootIndex); |
| 241 |
| 242 Comment("initialize undefined fields (no finalize)"); |
| 243 InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize), |
| 244 used_size, Heap::kUndefinedValueRootIndex); |
| 245 Return(object); |
| 246 } |
| 247 |
| 248 { |
| 249 // Finalize the instance size. |
| 250 Bind(&finalize); |
| 251 |
| 252 Node* unused_fields = LoadObjectField( |
| 253 initial_map, Map::kUnusedPropertyFieldsOffset, MachineType::Uint8()); |
| 254 Node* used_size = |
| 255 IntPtrSub(instance_size, WordShl(ChangeUint32ToWord(unused_fields), |
| 256 IntPtrConstant(kPointerSizeLog2))); |
| 257 |
| 258 Comment("initialize filler fields (finalize)"); |
| 259 InitializeFieldsWithRoot(object, used_size, instance_size, |
| 260 Heap::kOnePointerFillerMapRootIndex); |
| 261 |
| 262 Comment("initialize undefined fields (finalize)"); |
| 263 InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize), |
| 264 used_size, Heap::kUndefinedValueRootIndex); |
| 265 |
| 266 CallRuntime(Runtime::kFinalizeInstanceSize, context, initial_map); |
| 267 Return(object); |
| 268 } |
| 269 } |
| 270 |
157 } // namespace internal | 271 } // namespace internal |
158 } // namespace v8 | 272 } // namespace v8 |
OLD | NEW |