Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: src/builtins/builtins-function.cc

Issue 2532483002: [stubs] Port FastFunctionBindStub to TF (Closed)
Patch Set: Review feedback Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins-array.cc ('k') | src/code-factory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.h" 5 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7 7
8 #include "src/code-factory.h"
8 #include "src/compiler.h" 9 #include "src/compiler.h"
9 #include "src/string-builder.h" 10 #include "src/string-builder.h"
10 11
11 namespace v8 { 12 namespace v8 {
12 namespace internal { 13 namespace internal {
13 14
14 namespace { 15 namespace {
15 16
16 // ES6 section 19.2.1.1.1 CreateDynamicFunction 17 // ES6 section 19.2.1.1.1 CreateDynamicFunction
17 MaybeHandle<Object> CreateDynamicFunction(Isolate* isolate, 18 MaybeHandle<Object> CreateDynamicFunction(Isolate* isolate,
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 &it, name, it.property_attributes())); 249 &it, name, it.property_attributes()));
249 } 250 }
250 return *function; 251 return *function;
251 } 252 }
252 253
253 } // namespace 254 } // namespace
254 255
255 // ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args ) 256 // ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
256 BUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); } 257 BUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); }
257 258
259 void Builtins::Generate_FastFunctionPrototypeBind(
260 compiler::CodeAssemblerState* state) {
261 using compiler::Node;
262 typedef CodeStubAssembler::Label Label;
263 typedef CodeStubAssembler::Variable Variable;
264
265 CodeStubAssembler assembler(state);
266 Label slow(&assembler);
267
268 Node* argc = assembler.Parameter(BuiltinDescriptor::kArgumentsCount);
269 Node* context = assembler.Parameter(BuiltinDescriptor::kContext);
270 Node* new_target = assembler.Parameter(BuiltinDescriptor::kNewTarget);
271
272 CodeStubArguments args(&assembler, argc);
273
274 // Check that receiver has instance type of JS_FUNCTION_TYPE
275 Node* receiver = args.GetReceiver();
276 assembler.GotoIf(assembler.TaggedIsSmi(receiver), &slow);
277
278 Node* receiver_map = assembler.LoadMap(receiver);
279 Node* instance_type = assembler.LoadMapInstanceType(receiver_map);
280 assembler.GotoIf(
281 assembler.Word32NotEqual(instance_type,
282 assembler.Int32Constant(JS_FUNCTION_TYPE)),
283 &slow);
284
285 // Disallow binding of slow-mode functions. We need to figure out whether the
286 // length and name property are in the original state.
287 assembler.Comment("Disallow binding of slow-mode functions");
288 assembler.GotoIf(assembler.IsDictionaryMap(receiver_map), &slow);
289
290 // Check whether the length and name properties are still present as
291 // AccessorInfo objects. In that case, their value can be recomputed even if
292 // the actual value on the object changes.
293 assembler.Comment("Check descriptor array length");
294 Node* descriptors =
295 assembler.LoadObjectField(receiver_map, Map::kDescriptorsOffset);
Igor Sheludko 2016/12/01 16:17:40 LoadMapDescriptors()
296 Node* descriptors_length = assembler.LoadFixedArrayBaseLength(descriptors);
297 assembler.GotoIf(assembler.SmiLessThanOrEqual(descriptors_length,
298 assembler.SmiConstant(1)),
299 &slow);
300
301 // Check whether the length and name properties are still present as
302 // AccessorInfo objects. In that case, their value can be recomputed even if
303 // the actual value on the object changes.
304 assembler.Comment("Check name and length properties");
305 const int length_index = JSFunction::kLengthDescriptorIndex;
306 Node* maybe_length = assembler.LoadFixedArrayElement(
307 descriptors,
308 assembler.IntPtrConstant(DescriptorArray::ToKeyIndex(length_index)),
Igor Sheludko 2016/12/01 16:17:40 The cleanup CL has landed and you can now write he
309 CodeStubAssembler::INTPTR_PARAMETERS);
310 assembler.GotoIf(
311 assembler.WordNotEqual(maybe_length,
312 assembler.LoadRoot(Heap::klength_stringRootIndex)),
313 &slow);
314
315 Node* maybe_length_accessor = assembler.LoadFixedArrayElement(
316 descriptors,
317 assembler.Int32Constant(DescriptorArray::ToValueIndex(length_index)));
318 assembler.GotoIf(assembler.TaggedIsSmi(maybe_length_accessor), &slow);
319 Node* length_value_map = assembler.LoadMap(maybe_length_accessor);
320 assembler.GotoUnless(assembler.IsAccessorInfoMap(length_value_map), &slow);
321
322 const int name_index = JSFunction::kNameDescriptorIndex;
323 Node* maybe_name = assembler.LoadFixedArrayElement(
324 descriptors,
325 assembler.IntPtrConstant(DescriptorArray::ToKeyIndex(name_index)),
326 CodeStubAssembler::INTPTR_PARAMETERS);
327 assembler.GotoIf(
328 assembler.WordNotEqual(maybe_name,
329 assembler.LoadRoot(Heap::kname_stringRootIndex)),
330 &slow);
331
332 Node* maybe_name_accessor = assembler.LoadFixedArrayElement(
333 descriptors,
334 assembler.IntPtrConstant(DescriptorArray::ToValueIndex(name_index)),
335 CodeStubAssembler::INTPTR_PARAMETERS);
336 assembler.GotoIf(assembler.TaggedIsSmi(maybe_name_accessor), &slow);
337 Node* name_value_map = assembler.LoadMap(maybe_name_accessor);
338 assembler.GotoUnless(assembler.IsAccessorInfoMap(name_value_map), &slow);
339
340 // Choose the right bound function map based on whether the target is
341 // constructable.
342 assembler.Comment("Choose the right bound function map");
343 Variable bound_function_map(&assembler, MachineRepresentation::kTagged);
344 Label with_constructor(&assembler);
345 CodeStubAssembler::VariableList vars({&bound_function_map}, assembler.zone());
346 Label map_done(&assembler, vars);
347 Node* bit_field = assembler.LoadMapBitField(receiver_map);
348 int mask = static_cast<int>(1 << Map::kIsConstructor);
349 assembler.GotoIf(assembler.IsSetWord32(bit_field, mask), &with_constructor);
350
351 Node* native_context = assembler.LoadNativeContext(context);
352 bound_function_map.Bind(assembler.LoadContextElement(
353 native_context, Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX));
354 assembler.Goto(&map_done);
355
356 assembler.Bind(&with_constructor);
357 bound_function_map.Bind(assembler.LoadContextElement(
Igor Sheludko 2016/12/01 16:17:40 I think native_context is not available in this bl
358 native_context, Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX));
359 assembler.Goto(&map_done);
360
361 assembler.Bind(&map_done);
362
363 // Verify that __proto__ matches that of a the target bound function.
364 assembler.Comment("Verify that __proto__ matches target bound function");
365 Node* prototype = assembler.LoadMapPrototype(receiver_map);
366 Node* expected_prototype =
367 assembler.LoadMapPrototype(bound_function_map.value());
368 assembler.GotoIf(assembler.WordNotEqual(prototype, expected_prototype),
369 &slow);
370
371 // Allocate the arguments array.
372 assembler.Comment("Allocate the arguments array");
373 Variable argument_array(&assembler, MachineRepresentation::kTagged);
374 Label empty_arguments(&assembler);
375 Label arguments_done(&assembler, &argument_array);
376 assembler.GotoIf(
377 assembler.UintPtrLessThanOrEqual(argc, assembler.IntPtrConstant(1)),
378 &empty_arguments);
379 Node* elements_length =
380 assembler.IntPtrSub(argc, assembler.IntPtrConstant(1));
381 Node* elements = assembler.AllocateFixedArray(
382 FAST_ELEMENTS, elements_length, CodeStubAssembler::INTPTR_PARAMETERS);
383 Variable index(&assembler, MachineType::PointerRepresentation());
384 index.Bind(assembler.IntPtrConstant(0));
385 CodeStubAssembler::VariableList foreach_vars({&index}, assembler.zone());
386 args.ForEach(
387 foreach_vars,
388 [elements, &index](CodeStubAssembler* assembler, compiler::Node* arg) {
389 assembler->StoreFixedArrayElement(elements, index.value(), arg,
390 UPDATE_WRITE_BARRIER, 0,
391 CodeStubAssembler::INTPTR_PARAMETERS);
392 assembler->Increment(index);
393 },
394 assembler.IntPtrConstant(1));
395 argument_array.Bind(elements);
396 assembler.Goto(&arguments_done);
397
398 assembler.Bind(&empty_arguments);
399 argument_array.Bind(assembler.EmptyFixedArrayConstant());
400 assembler.Goto(&arguments_done);
401
402 assembler.Bind(&arguments_done);
403
404 // Determine bound receiver.
405 assembler.Comment("Determine bound receiver");
406 Variable bound_receiver(&assembler, MachineRepresentation::kTagged);
407 Label has_receiver(&assembler);
408 Label receiver_done(&assembler, &bound_receiver);
409 assembler.GotoIf(assembler.WordNotEqual(argc, assembler.IntPtrConstant(0)),
410 &has_receiver);
411 bound_receiver.Bind(assembler.UndefinedConstant());
412 assembler.Goto(&receiver_done);
413
414 assembler.Bind(&has_receiver);
415 bound_receiver.Bind(args.AtIndex(0));
416 assembler.Goto(&receiver_done);
417
418 assembler.Bind(&receiver_done);
419
420 // Allocate the resulting bound function.
421 assembler.Comment("Allocate the resulting bound function");
422 Node* bound_function = assembler.Allocate(JSBoundFunction::kSize);
423 assembler.StoreMapNoWriteBarrier(bound_function, bound_function_map.value());
424 assembler.StoreObjectFieldNoWriteBarrier(
425 bound_function, JSBoundFunction::kBoundTargetFunctionOffset, receiver);
426 assembler.StoreObjectFieldNoWriteBarrier(bound_function,
427 JSBoundFunction::kBoundThisOffset,
428 bound_receiver.value());
429 assembler.StoreObjectFieldNoWriteBarrier(
430 bound_function, JSBoundFunction::kBoundArgumentsOffset,
431 argument_array.value());
432 Node* empty_fixed_array = assembler.EmptyFixedArrayConstant();
433 assembler.StoreObjectFieldNoWriteBarrier(
434 bound_function, JSObject::kPropertiesOffset, empty_fixed_array);
435 assembler.StoreObjectFieldNoWriteBarrier(
436 bound_function, JSObject::kElementsOffset, empty_fixed_array);
437
438 args.PopAndReturn(bound_function);
439 assembler.Bind(&slow);
440
441 Node* target = assembler.LoadFromFrame(
442 StandardFrameConstants::kFunctionOffset, MachineType::TaggedPointer());
443 assembler.TailCallStub(
444 CodeFactory::FunctionPrototypeBind(assembler.isolate()), context, target,
445 new_target, argc);
446 }
447
258 // TODO(verwaest): This is a temporary helper until the FastFunctionBind stub 448 // TODO(verwaest): This is a temporary helper until the FastFunctionBind stub
259 // can tailcall to the builtin directly. 449 // can tailcall to the builtin directly.
260 RUNTIME_FUNCTION(Runtime_FunctionBind) { 450 RUNTIME_FUNCTION(Runtime_FunctionBind) {
261 DCHECK_EQ(2, args.length()); 451 DCHECK_EQ(2, args.length());
262 Arguments* incoming = reinterpret_cast<Arguments*>(args[0]); 452 Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
263 // Rewrap the arguments as builtins arguments. 453 // Rewrap the arguments as builtins arguments.
264 int argc = incoming->length() + BuiltinArguments::kNumExtraArgsWithReceiver; 454 int argc = incoming->length() + BuiltinArguments::kNumExtraArgsWithReceiver;
265 BuiltinArguments caller_args(argc, incoming->arguments() + 1); 455 BuiltinArguments caller_args(argc, incoming->arguments() + 1);
266 return DoFunctionBind(isolate, caller_args); 456 return DoFunctionBind(isolate, caller_args);
267 } 457 }
(...skipping 21 matching lines...) Expand all
289 479
290 Node* f = assembler.Parameter(0); 480 Node* f = assembler.Parameter(0);
291 Node* v = assembler.Parameter(1); 481 Node* v = assembler.Parameter(1);
292 Node* context = assembler.Parameter(4); 482 Node* context = assembler.Parameter(4);
293 Node* result = assembler.OrdinaryHasInstance(context, f, v); 483 Node* result = assembler.OrdinaryHasInstance(context, f, v);
294 assembler.Return(result); 484 assembler.Return(result);
295 } 485 }
296 486
297 } // namespace internal 487 } // namespace internal
298 } // namespace v8 488 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-array.cc ('k') | src/code-factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698