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 |