| 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 | 
|---|