| 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/ast/ast.h" | 6 #include "src/ast/ast.h" |
| 7 #include "src/builtins/builtins-utils.h" | 7 #include "src/builtins/builtins-utils.h" |
| 8 #include "src/builtins/builtins.h" | 8 #include "src/builtins/builtins.h" |
| 9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/code-stub-assembler.h" | 10 #include "src/code-stub-assembler.h" |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 Node* context = Parameter(FastNewClosureDescriptor::kContext); | 154 Node* context = Parameter(FastNewClosureDescriptor::kContext); |
| 155 Return(EmitFastNewClosure(shared, context)); | 155 Return(EmitFastNewClosure(shared, context)); |
| 156 } | 156 } |
| 157 | 157 |
| 158 TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) { | 158 TF_BUILTIN(FastNewObject, ConstructorBuiltinsAssembler) { |
| 159 typedef FastNewObjectDescriptor Descriptor; | 159 typedef FastNewObjectDescriptor Descriptor; |
| 160 Node* context = Parameter(Descriptor::kContext); | 160 Node* context = Parameter(Descriptor::kContext); |
| 161 Node* target = Parameter(Descriptor::kTarget); | 161 Node* target = Parameter(Descriptor::kTarget); |
| 162 Node* new_target = Parameter(Descriptor::kNewTarget); | 162 Node* new_target = Parameter(Descriptor::kNewTarget); |
| 163 | 163 |
| 164 Label call_runtime(this); |
| 165 |
| 166 Node* result = EmitFastNewObject(context, target, new_target, &call_runtime); |
| 167 Return(result); |
| 168 |
| 169 Bind(&call_runtime); |
| 170 TailCallRuntime(Runtime::kNewObject, context, target, new_target); |
| 171 } |
| 172 |
| 173 Node* ConstructorBuiltinsAssembler::EmitFastNewObject(Node* context, |
| 174 Node* target, |
| 175 Node* new_target) { |
| 176 Variable var_obj(this, MachineRepresentation::kTagged); |
| 177 Label call_runtime(this), end(this); |
| 178 |
| 179 Node* result = EmitFastNewObject(context, target, new_target, &call_runtime); |
| 180 var_obj.Bind(result); |
| 181 Goto(&end); |
| 182 |
| 183 Bind(&call_runtime); |
| 184 var_obj.Bind(CallRuntime(Runtime::kNewObject, context, target, new_target)); |
| 185 Goto(&end); |
| 186 |
| 187 Bind(&end); |
| 188 return var_obj.value(); |
| 189 } |
| 190 |
| 191 Node* ConstructorBuiltinsAssembler::EmitFastNewObject( |
| 192 Node* context, Node* target, Node* new_target, |
| 193 CodeAssemblerLabel* call_runtime) { |
| 164 CSA_ASSERT(this, HasInstanceType(target, JS_FUNCTION_TYPE)); | 194 CSA_ASSERT(this, HasInstanceType(target, JS_FUNCTION_TYPE)); |
| 165 CSA_ASSERT(this, IsJSReceiver(new_target)); | 195 CSA_ASSERT(this, IsJSReceiver(new_target)); |
| 166 | 196 |
| 167 // Verify that the new target is a JSFunction. | 197 // Verify that the new target is a JSFunction. |
| 168 Label runtime(this), fast(this); | 198 Label fast(this), end(this); |
| 169 GotoIf(HasInstanceType(new_target, JS_FUNCTION_TYPE), &fast); | 199 GotoIf(HasInstanceType(new_target, JS_FUNCTION_TYPE), &fast); |
| 170 Goto(&runtime); | 200 Goto(call_runtime); |
| 171 | |
| 172 Bind(&runtime); | |
| 173 TailCallRuntime(Runtime::kNewObject, context, target, new_target); | |
| 174 | 201 |
| 175 Bind(&fast); | 202 Bind(&fast); |
| 176 | 203 |
| 177 // Load the initial map and verify that it's in fact a map. | 204 // Load the initial map and verify that it's in fact a map. |
| 178 Node* initial_map = | 205 Node* initial_map = |
| 179 LoadObjectField(new_target, JSFunction::kPrototypeOrInitialMapOffset); | 206 LoadObjectField(new_target, JSFunction::kPrototypeOrInitialMapOffset); |
| 180 GotoIf(TaggedIsSmi(initial_map), &runtime); | 207 GotoIf(TaggedIsSmi(initial_map), call_runtime); |
| 181 GotoIf(DoesntHaveInstanceType(initial_map, MAP_TYPE), &runtime); | 208 GotoIf(DoesntHaveInstanceType(initial_map, MAP_TYPE), call_runtime); |
| 182 | 209 |
| 183 // Fall back to runtime if the target differs from the new target's | 210 // Fall back to runtime if the target differs from the new target's |
| 184 // initial map constructor. | 211 // initial map constructor. |
| 185 Node* new_target_constructor = | 212 Node* new_target_constructor = |
| 186 LoadObjectField(initial_map, Map::kConstructorOrBackPointerOffset); | 213 LoadObjectField(initial_map, Map::kConstructorOrBackPointerOffset); |
| 187 GotoIf(WordNotEqual(target, new_target_constructor), &runtime); | 214 GotoIf(WordNotEqual(target, new_target_constructor), call_runtime); |
| 188 | 215 |
| 189 Node* instance_size_words = ChangeUint32ToWord(LoadObjectField( | 216 Node* instance_size_words = ChangeUint32ToWord(LoadObjectField( |
| 190 initial_map, Map::kInstanceSizeOffset, MachineType::Uint8())); | 217 initial_map, Map::kInstanceSizeOffset, MachineType::Uint8())); |
| 191 Node* instance_size = | 218 Node* instance_size = |
| 192 WordShl(instance_size_words, IntPtrConstant(kPointerSizeLog2)); | 219 WordShl(instance_size_words, IntPtrConstant(kPointerSizeLog2)); |
| 193 | 220 |
| 194 Node* object = Allocate(instance_size); | 221 Node* object = Allocate(instance_size); |
| 195 StoreMapNoWriteBarrier(object, initial_map); | 222 StoreMapNoWriteBarrier(object, initial_map); |
| 196 Node* empty_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex); | 223 Node* empty_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex); |
| 197 StoreObjectFieldNoWriteBarrier(object, JSObject::kPropertiesOffset, | 224 StoreObjectFieldNoWriteBarrier(object, JSObject::kPropertiesOffset, |
| 198 empty_array); | 225 empty_array); |
| 199 StoreObjectFieldNoWriteBarrier(object, JSObject::kElementsOffset, | 226 StoreObjectFieldNoWriteBarrier(object, JSObject::kElementsOffset, |
| 200 empty_array); | 227 empty_array); |
| 201 | 228 |
| 202 instance_size_words = ChangeUint32ToWord(LoadObjectField( | 229 instance_size_words = ChangeUint32ToWord(LoadObjectField( |
| 203 initial_map, Map::kInstanceSizeOffset, MachineType::Uint8())); | 230 initial_map, Map::kInstanceSizeOffset, MachineType::Uint8())); |
| 204 instance_size = | 231 instance_size = |
| 205 WordShl(instance_size_words, IntPtrConstant(kPointerSizeLog2)); | 232 WordShl(instance_size_words, IntPtrConstant(kPointerSizeLog2)); |
| 206 | 233 |
| 207 // Perform in-object slack tracking if requested. | 234 // Perform in-object slack tracking if requested. |
| 208 Node* bit_field3 = LoadMapBitField3(initial_map); | 235 Node* bit_field3 = LoadMapBitField3(initial_map); |
| 209 Label slack_tracking(this), finalize(this, Label::kDeferred), done(this); | 236 Label slack_tracking(this), finalize(this, Label::kDeferred), done(this); |
| 210 GotoIf(IsSetWord32<Map::ConstructionCounter>(bit_field3), &slack_tracking); | 237 GotoIf(IsSetWord32<Map::ConstructionCounter>(bit_field3), &slack_tracking); |
| 211 | 238 |
| 212 // Initialize remaining fields. | 239 // Initialize remaining fields. |
| 213 { | 240 { |
| 214 Comment("no slack tracking"); | 241 Comment("no slack tracking"); |
| 215 InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize), | 242 InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize), |
| 216 instance_size, Heap::kUndefinedValueRootIndex); | 243 instance_size, Heap::kUndefinedValueRootIndex); |
| 217 Return(object); | 244 Goto(&end); |
| 218 } | 245 } |
| 219 | 246 |
| 220 { | 247 { |
| 221 Bind(&slack_tracking); | 248 Bind(&slack_tracking); |
| 222 | 249 |
| 223 // Decrease generous allocation count. | 250 // Decrease generous allocation count. |
| 224 STATIC_ASSERT(Map::ConstructionCounter::kNext == 32); | 251 STATIC_ASSERT(Map::ConstructionCounter::kNext == 32); |
| 225 Comment("update allocation count"); | 252 Comment("update allocation count"); |
| 226 Node* new_bit_field3 = Int32Sub( | 253 Node* new_bit_field3 = Int32Sub( |
| 227 bit_field3, Int32Constant(1 << Map::ConstructionCounter::kShift)); | 254 bit_field3, Int32Constant(1 << Map::ConstructionCounter::kShift)); |
| 228 StoreObjectFieldNoWriteBarrier(initial_map, Map::kBitField3Offset, | 255 StoreObjectFieldNoWriteBarrier(initial_map, Map::kBitField3Offset, |
| 229 new_bit_field3, | 256 new_bit_field3, |
| 230 MachineRepresentation::kWord32); | 257 MachineRepresentation::kWord32); |
| 231 GotoIf(IsClearWord32<Map::ConstructionCounter>(new_bit_field3), &finalize); | 258 GotoIf(IsClearWord32<Map::ConstructionCounter>(new_bit_field3), &finalize); |
| 232 | 259 |
| 233 Node* unused_fields = LoadObjectField( | 260 Node* unused_fields = LoadObjectField( |
| 234 initial_map, Map::kUnusedPropertyFieldsOffset, MachineType::Uint8()); | 261 initial_map, Map::kUnusedPropertyFieldsOffset, MachineType::Uint8()); |
| 235 Node* used_size = | 262 Node* used_size = |
| 236 IntPtrSub(instance_size, WordShl(ChangeUint32ToWord(unused_fields), | 263 IntPtrSub(instance_size, WordShl(ChangeUint32ToWord(unused_fields), |
| 237 IntPtrConstant(kPointerSizeLog2))); | 264 IntPtrConstant(kPointerSizeLog2))); |
| 238 | 265 |
| 239 Comment("initialize filler fields (no finalize)"); | 266 Comment("initialize filler fields (no finalize)"); |
| 240 InitializeFieldsWithRoot(object, used_size, instance_size, | 267 InitializeFieldsWithRoot(object, used_size, instance_size, |
| 241 Heap::kOnePointerFillerMapRootIndex); | 268 Heap::kOnePointerFillerMapRootIndex); |
| 242 | 269 |
| 243 Comment("initialize undefined fields (no finalize)"); | 270 Comment("initialize undefined fields (no finalize)"); |
| 244 InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize), | 271 InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize), |
| 245 used_size, Heap::kUndefinedValueRootIndex); | 272 used_size, Heap::kUndefinedValueRootIndex); |
| 246 Return(object); | 273 Goto(&end); |
| 247 } | 274 } |
| 248 | 275 |
| 249 { | 276 { |
| 250 // Finalize the instance size. | 277 // Finalize the instance size. |
| 251 Bind(&finalize); | 278 Bind(&finalize); |
| 252 | 279 |
| 253 Node* unused_fields = LoadObjectField( | 280 Node* unused_fields = LoadObjectField( |
| 254 initial_map, Map::kUnusedPropertyFieldsOffset, MachineType::Uint8()); | 281 initial_map, Map::kUnusedPropertyFieldsOffset, MachineType::Uint8()); |
| 255 Node* used_size = | 282 Node* used_size = |
| 256 IntPtrSub(instance_size, WordShl(ChangeUint32ToWord(unused_fields), | 283 IntPtrSub(instance_size, WordShl(ChangeUint32ToWord(unused_fields), |
| 257 IntPtrConstant(kPointerSizeLog2))); | 284 IntPtrConstant(kPointerSizeLog2))); |
| 258 | 285 |
| 259 Comment("initialize filler fields (finalize)"); | 286 Comment("initialize filler fields (finalize)"); |
| 260 InitializeFieldsWithRoot(object, used_size, instance_size, | 287 InitializeFieldsWithRoot(object, used_size, instance_size, |
| 261 Heap::kOnePointerFillerMapRootIndex); | 288 Heap::kOnePointerFillerMapRootIndex); |
| 262 | 289 |
| 263 Comment("initialize undefined fields (finalize)"); | 290 Comment("initialize undefined fields (finalize)"); |
| 264 InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize), | 291 InitializeFieldsWithRoot(object, IntPtrConstant(JSObject::kHeaderSize), |
| 265 used_size, Heap::kUndefinedValueRootIndex); | 292 used_size, Heap::kUndefinedValueRootIndex); |
| 266 | 293 |
| 267 CallRuntime(Runtime::kFinalizeInstanceSize, context, initial_map); | 294 CallRuntime(Runtime::kFinalizeInstanceSize, context, initial_map); |
| 268 Return(object); | 295 Goto(&end); |
| 269 } | 296 } |
| 297 |
| 298 Bind(&end); |
| 299 return object; |
| 270 } | 300 } |
| 271 | 301 |
| 272 Node* ConstructorBuiltinsAssembler::EmitFastNewFunctionContext( | 302 Node* ConstructorBuiltinsAssembler::EmitFastNewFunctionContext( |
| 273 Node* function, Node* slots, Node* context, ScopeType scope_type) { | 303 Node* function, Node* slots, Node* context, ScopeType scope_type) { |
| 274 slots = ChangeUint32ToWord(slots); | 304 slots = ChangeUint32ToWord(slots); |
| 275 | 305 |
| 276 // TODO(ishell): Use CSA::OptimalParameterMode() here. | 306 // TODO(ishell): Use CSA::OptimalParameterMode() here. |
| 277 CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; | 307 CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; |
| 278 Node* min_context_slots = IntPtrConstant(Context::MIN_CONTEXT_SLOTS); | 308 Node* min_context_slots = IntPtrConstant(Context::MIN_CONTEXT_SLOTS); |
| 279 Node* length = IntPtrAdd(slots, min_context_slots); | 309 Node* length = IntPtrAdd(slots, min_context_slots); |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 case 6: | 763 case 6: |
| 734 return FastCloneShallowObject6(); | 764 return FastCloneShallowObject6(); |
| 735 default: | 765 default: |
| 736 UNREACHABLE(); | 766 UNREACHABLE(); |
| 737 } | 767 } |
| 738 return Handle<Code>::null(); | 768 return Handle<Code>::null(); |
| 739 } | 769 } |
| 740 | 770 |
| 741 } // namespace internal | 771 } // namespace internal |
| 742 } // namespace v8 | 772 } // namespace v8 |
| OLD | NEW |