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

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

Issue 2734323004: [cleanup] Refactor remaining builtins-*.cc to use TF_BUILTIN macro (Closed)
Patch Set: drop unused variable Created 3 years, 9 months 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-date.cc ('k') | src/builtins/builtins-global.cc » ('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-utils.h" 5 #include "src/builtins/builtins-utils.h"
6 #include "src/builtins/builtins.h" 6 #include "src/builtins/builtins.h"
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/code-stub-assembler.h" 8 #include "src/code-stub-assembler.h"
9 #include "src/compiler.h" 9 #include "src/compiler.h"
10 #include "src/conversions.h" 10 #include "src/conversions.h"
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 &it, name, it.property_attributes())); 265 &it, name, it.property_attributes()));
266 } 266 }
267 return *function; 267 return *function;
268 } 268 }
269 269
270 } // namespace 270 } // namespace
271 271
272 // ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args ) 272 // ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
273 BUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); } 273 BUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); }
274 274
275 void Builtins::Generate_FastFunctionPrototypeBind( 275 TF_BUILTIN(FastFunctionPrototypeBind, CodeStubAssembler) {
276 compiler::CodeAssemblerState* state) { 276 Label slow(this);
277 using compiler::Node;
278 typedef CodeStubAssembler::Label Label;
279 typedef CodeStubAssembler::Variable Variable;
280 277
281 CodeStubAssembler assembler(state); 278 Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
282 Label slow(&assembler); 279 Node* context = Parameter(BuiltinDescriptor::kContext);
280 Node* new_target = Parameter(BuiltinDescriptor::kNewTarget);
283 281
284 Node* argc = assembler.Parameter(BuiltinDescriptor::kArgumentsCount); 282 CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
285 Node* context = assembler.Parameter(BuiltinDescriptor::kContext);
286 Node* new_target = assembler.Parameter(BuiltinDescriptor::kNewTarget);
287
288 CodeStubArguments args(&assembler, assembler.ChangeInt32ToIntPtr(argc));
289 283
290 // Check that receiver has instance type of JS_FUNCTION_TYPE 284 // Check that receiver has instance type of JS_FUNCTION_TYPE
291 Node* receiver = args.GetReceiver(); 285 Node* receiver = args.GetReceiver();
292 assembler.GotoIf(assembler.TaggedIsSmi(receiver), &slow); 286 GotoIf(TaggedIsSmi(receiver), &slow);
293 287
294 Node* receiver_map = assembler.LoadMap(receiver); 288 Node* receiver_map = LoadMap(receiver);
295 Node* instance_type = assembler.LoadMapInstanceType(receiver_map); 289 Node* instance_type = LoadMapInstanceType(receiver_map);
296 assembler.GotoIf( 290 GotoIf(Word32NotEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)), &slow);
297 assembler.Word32NotEqual(instance_type,
298 assembler.Int32Constant(JS_FUNCTION_TYPE)),
299 &slow);
300 291
301 // Disallow binding of slow-mode functions. We need to figure out whether the 292 // Disallow binding of slow-mode functions. We need to figure out whether the
302 // length and name property are in the original state. 293 // length and name property are in the original state.
303 assembler.Comment("Disallow binding of slow-mode functions"); 294 Comment("Disallow binding of slow-mode functions");
304 assembler.GotoIf(assembler.IsDictionaryMap(receiver_map), &slow); 295 GotoIf(IsDictionaryMap(receiver_map), &slow);
305 296
306 // Check whether the length and name properties are still present as 297 // Check whether the length and name properties are still present as
307 // AccessorInfo objects. In that case, their value can be recomputed even if 298 // AccessorInfo objects. In that case, their value can be recomputed even if
308 // the actual value on the object changes. 299 // the actual value on the object changes.
309 assembler.Comment("Check descriptor array length"); 300 Comment("Check descriptor array length");
310 Node* descriptors = assembler.LoadMapDescriptors(receiver_map); 301 Node* descriptors = LoadMapDescriptors(receiver_map);
311 Node* descriptors_length = assembler.LoadFixedArrayBaseLength(descriptors); 302 Node* descriptors_length = LoadFixedArrayBaseLength(descriptors);
312 assembler.GotoIf(assembler.SmiLessThanOrEqual(descriptors_length, 303 GotoIf(SmiLessThanOrEqual(descriptors_length, SmiConstant(1)), &slow);
313 assembler.SmiConstant(1)),
314 &slow);
315 304
316 // Check whether the length and name properties are still present as 305 // Check whether the length and name properties are still present as
317 // AccessorInfo objects. In that case, their value can be recomputed even if 306 // AccessorInfo objects. In that case, their value can be recomputed even if
318 // the actual value on the object changes. 307 // the actual value on the object changes.
319 assembler.Comment("Check name and length properties"); 308 Comment("Check name and length properties");
320 const int length_index = JSFunction::kLengthDescriptorIndex; 309 const int length_index = JSFunction::kLengthDescriptorIndex;
321 Node* maybe_length = assembler.LoadFixedArrayElement( 310 Node* maybe_length = LoadFixedArrayElement(
322 descriptors, DescriptorArray::ToKeyIndex(length_index)); 311 descriptors, DescriptorArray::ToKeyIndex(length_index));
323 assembler.GotoIf( 312 GotoIf(WordNotEqual(maybe_length, LoadRoot(Heap::klength_stringRootIndex)),
324 assembler.WordNotEqual(maybe_length, 313 &slow);
325 assembler.LoadRoot(Heap::klength_stringRootIndex)),
326 &slow);
327 314
328 Node* maybe_length_accessor = assembler.LoadFixedArrayElement( 315 Node* maybe_length_accessor = LoadFixedArrayElement(
329 descriptors, DescriptorArray::ToValueIndex(length_index)); 316 descriptors, DescriptorArray::ToValueIndex(length_index));
330 assembler.GotoIf(assembler.TaggedIsSmi(maybe_length_accessor), &slow); 317 GotoIf(TaggedIsSmi(maybe_length_accessor), &slow);
331 Node* length_value_map = assembler.LoadMap(maybe_length_accessor); 318 Node* length_value_map = LoadMap(maybe_length_accessor);
332 assembler.GotoIfNot(assembler.IsAccessorInfoMap(length_value_map), &slow); 319 GotoIfNot(IsAccessorInfoMap(length_value_map), &slow);
333 320
334 const int name_index = JSFunction::kNameDescriptorIndex; 321 const int name_index = JSFunction::kNameDescriptorIndex;
335 Node* maybe_name = assembler.LoadFixedArrayElement( 322 Node* maybe_name = LoadFixedArrayElement(
336 descriptors, DescriptorArray::ToKeyIndex(name_index)); 323 descriptors, DescriptorArray::ToKeyIndex(name_index));
337 assembler.GotoIf( 324 GotoIf(WordNotEqual(maybe_name, LoadRoot(Heap::kname_stringRootIndex)),
338 assembler.WordNotEqual(maybe_name, 325 &slow);
339 assembler.LoadRoot(Heap::kname_stringRootIndex)),
340 &slow);
341 326
342 Node* maybe_name_accessor = assembler.LoadFixedArrayElement( 327 Node* maybe_name_accessor = LoadFixedArrayElement(
343 descriptors, DescriptorArray::ToValueIndex(name_index)); 328 descriptors, DescriptorArray::ToValueIndex(name_index));
344 assembler.GotoIf(assembler.TaggedIsSmi(maybe_name_accessor), &slow); 329 GotoIf(TaggedIsSmi(maybe_name_accessor), &slow);
345 Node* name_value_map = assembler.LoadMap(maybe_name_accessor); 330 Node* name_value_map = LoadMap(maybe_name_accessor);
346 assembler.GotoIfNot(assembler.IsAccessorInfoMap(name_value_map), &slow); 331 GotoIfNot(IsAccessorInfoMap(name_value_map), &slow);
347 332
348 // Choose the right bound function map based on whether the target is 333 // Choose the right bound function map based on whether the target is
349 // constructable. 334 // constructable.
350 assembler.Comment("Choose the right bound function map"); 335 Comment("Choose the right bound function map");
351 Variable bound_function_map(&assembler, MachineRepresentation::kTagged); 336 Variable bound_function_map(this, MachineRepresentation::kTagged);
352 Label with_constructor(&assembler); 337 Label with_constructor(this);
353 CodeStubAssembler::VariableList vars({&bound_function_map}, assembler.zone()); 338 VariableList vars({&bound_function_map}, zone());
354 Node* native_context = assembler.LoadNativeContext(context); 339 Node* native_context = LoadNativeContext(context);
355 340
356 Label map_done(&assembler, vars); 341 Label map_done(this, vars);
357 Node* bit_field = assembler.LoadMapBitField(receiver_map); 342 Node* bit_field = LoadMapBitField(receiver_map);
358 int mask = static_cast<int>(1 << Map::kIsConstructor); 343 int mask = static_cast<int>(1 << Map::kIsConstructor);
359 assembler.GotoIf(assembler.IsSetWord32(bit_field, mask), &with_constructor); 344 GotoIf(IsSetWord32(bit_field, mask), &with_constructor);
360 345
361 bound_function_map.Bind(assembler.LoadContextElement( 346 bound_function_map.Bind(LoadContextElement(
362 native_context, Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX)); 347 native_context, Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX));
363 assembler.Goto(&map_done); 348 Goto(&map_done);
364 349
365 assembler.Bind(&with_constructor); 350 Bind(&with_constructor);
366 bound_function_map.Bind(assembler.LoadContextElement( 351 bound_function_map.Bind(LoadContextElement(
367 native_context, Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX)); 352 native_context, Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX));
368 assembler.Goto(&map_done); 353 Goto(&map_done);
369 354
370 assembler.Bind(&map_done); 355 Bind(&map_done);
371 356
372 // Verify that __proto__ matches that of a the target bound function. 357 // Verify that __proto__ matches that of a the target bound function.
373 assembler.Comment("Verify that __proto__ matches target bound function"); 358 Comment("Verify that __proto__ matches target bound function");
374 Node* prototype = assembler.LoadMapPrototype(receiver_map); 359 Node* prototype = LoadMapPrototype(receiver_map);
375 Node* expected_prototype = 360 Node* expected_prototype = LoadMapPrototype(bound_function_map.value());
376 assembler.LoadMapPrototype(bound_function_map.value()); 361 GotoIf(WordNotEqual(prototype, expected_prototype), &slow);
377 assembler.GotoIf(assembler.WordNotEqual(prototype, expected_prototype),
378 &slow);
379 362
380 // Allocate the arguments array. 363 // Allocate the arguments array.
381 assembler.Comment("Allocate the arguments array"); 364 Comment("Allocate the arguments array");
382 Variable argument_array(&assembler, MachineRepresentation::kTagged); 365 Variable argument_array(this, MachineRepresentation::kTagged);
383 Label empty_arguments(&assembler); 366 Label empty_arguments(this);
384 Label arguments_done(&assembler, &argument_array); 367 Label arguments_done(this, &argument_array);
385 assembler.GotoIf( 368 GotoIf(Uint32LessThanOrEqual(argc, Int32Constant(1)), &empty_arguments);
386 assembler.Uint32LessThanOrEqual(argc, assembler.Int32Constant(1)), 369 Node* elements_length = ChangeUint32ToWord(Int32Sub(argc, Int32Constant(1)));
387 &empty_arguments); 370 Node* elements = AllocateFixedArray(FAST_ELEMENTS, elements_length);
388 Node* elements_length = assembler.ChangeUint32ToWord( 371 Variable index(this, MachineType::PointerRepresentation());
389 assembler.Int32Sub(argc, assembler.Int32Constant(1))); 372 index.Bind(IntPtrConstant(0));
390 Node* elements = assembler.AllocateFixedArray(FAST_ELEMENTS, elements_length); 373 VariableList foreach_vars({&index}, zone());
391 Variable index(&assembler, MachineType::PointerRepresentation());
392 index.Bind(assembler.IntPtrConstant(0));
393 CodeStubAssembler::VariableList foreach_vars({&index}, assembler.zone());
394 args.ForEach(foreach_vars, 374 args.ForEach(foreach_vars,
395 [&assembler, elements, &index](compiler::Node* arg) { 375 [this, elements, &index](Node* arg) {
396 assembler.StoreFixedArrayElement(elements, index.value(), arg); 376 StoreFixedArrayElement(elements, index.value(), arg);
397 assembler.Increment(index); 377 Increment(index);
398 }, 378 },
399 assembler.IntPtrConstant(1)); 379 IntPtrConstant(1));
400 argument_array.Bind(elements); 380 argument_array.Bind(elements);
401 assembler.Goto(&arguments_done); 381 Goto(&arguments_done);
402 382
403 assembler.Bind(&empty_arguments); 383 Bind(&empty_arguments);
404 argument_array.Bind(assembler.EmptyFixedArrayConstant()); 384 argument_array.Bind(EmptyFixedArrayConstant());
405 assembler.Goto(&arguments_done); 385 Goto(&arguments_done);
406 386
407 assembler.Bind(&arguments_done); 387 Bind(&arguments_done);
408 388
409 // Determine bound receiver. 389 // Determine bound receiver.
410 assembler.Comment("Determine bound receiver"); 390 Comment("Determine bound receiver");
411 Variable bound_receiver(&assembler, MachineRepresentation::kTagged); 391 Variable bound_receiver(this, MachineRepresentation::kTagged);
412 Label has_receiver(&assembler); 392 Label has_receiver(this);
413 Label receiver_done(&assembler, &bound_receiver); 393 Label receiver_done(this, &bound_receiver);
414 assembler.GotoIf(assembler.Word32NotEqual(argc, assembler.Int32Constant(0)), 394 GotoIf(Word32NotEqual(argc, Int32Constant(0)), &has_receiver);
415 &has_receiver); 395 bound_receiver.Bind(UndefinedConstant());
416 bound_receiver.Bind(assembler.UndefinedConstant()); 396 Goto(&receiver_done);
417 assembler.Goto(&receiver_done);
418 397
419 assembler.Bind(&has_receiver); 398 Bind(&has_receiver);
420 bound_receiver.Bind(args.AtIndex(0)); 399 bound_receiver.Bind(args.AtIndex(0));
421 assembler.Goto(&receiver_done); 400 Goto(&receiver_done);
422 401
423 assembler.Bind(&receiver_done); 402 Bind(&receiver_done);
424 403
425 // Allocate the resulting bound function. 404 // Allocate the resulting bound function.
426 assembler.Comment("Allocate the resulting bound function"); 405 Comment("Allocate the resulting bound function");
427 Node* bound_function = assembler.Allocate(JSBoundFunction::kSize); 406 Node* bound_function = Allocate(JSBoundFunction::kSize);
428 assembler.StoreMapNoWriteBarrier(bound_function, bound_function_map.value()); 407 StoreMapNoWriteBarrier(bound_function, bound_function_map.value());
429 assembler.StoreObjectFieldNoWriteBarrier( 408 StoreObjectFieldNoWriteBarrier(
430 bound_function, JSBoundFunction::kBoundTargetFunctionOffset, receiver); 409 bound_function, JSBoundFunction::kBoundTargetFunctionOffset, receiver);
431 assembler.StoreObjectFieldNoWriteBarrier(bound_function, 410 StoreObjectFieldNoWriteBarrier(bound_function,
432 JSBoundFunction::kBoundThisOffset, 411 JSBoundFunction::kBoundThisOffset,
433 bound_receiver.value()); 412 bound_receiver.value());
434 assembler.StoreObjectFieldNoWriteBarrier( 413 StoreObjectFieldNoWriteBarrier(bound_function,
435 bound_function, JSBoundFunction::kBoundArgumentsOffset, 414 JSBoundFunction::kBoundArgumentsOffset,
436 argument_array.value()); 415 argument_array.value());
437 Node* empty_fixed_array = assembler.EmptyFixedArrayConstant(); 416 Node* empty_fixed_array = EmptyFixedArrayConstant();
438 assembler.StoreObjectFieldNoWriteBarrier( 417 StoreObjectFieldNoWriteBarrier(bound_function, JSObject::kPropertiesOffset,
439 bound_function, JSObject::kPropertiesOffset, empty_fixed_array); 418 empty_fixed_array);
440 assembler.StoreObjectFieldNoWriteBarrier( 419 StoreObjectFieldNoWriteBarrier(bound_function, JSObject::kElementsOffset,
441 bound_function, JSObject::kElementsOffset, empty_fixed_array); 420 empty_fixed_array);
442 421
443 args.PopAndReturn(bound_function); 422 args.PopAndReturn(bound_function);
444 assembler.Bind(&slow); 423 Bind(&slow);
445 424
446 Node* target = assembler.LoadFromFrame( 425 Node* target = LoadFromFrame(StandardFrameConstants::kFunctionOffset,
447 StandardFrameConstants::kFunctionOffset, MachineType::TaggedPointer()); 426 MachineType::TaggedPointer());
448 assembler.TailCallStub( 427 TailCallStub(CodeFactory::FunctionPrototypeBind(isolate()), context, target,
449 CodeFactory::FunctionPrototypeBind(assembler.isolate()), context, target, 428 new_target, argc);
450 new_target, argc);
451 } 429 }
452 430
453 // TODO(verwaest): This is a temporary helper until the FastFunctionBind stub 431 // TODO(verwaest): This is a temporary helper until the FastFunctionBind stub
454 // can tailcall to the builtin directly. 432 // can tailcall to the builtin directly.
455 RUNTIME_FUNCTION(Runtime_FunctionBind) { 433 RUNTIME_FUNCTION(Runtime_FunctionBind) {
456 DCHECK_EQ(2, args.length()); 434 DCHECK_EQ(2, args.length());
457 Arguments* incoming = reinterpret_cast<Arguments*>(args[0]); 435 Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
458 // Rewrap the arguments as builtins arguments. 436 // Rewrap the arguments as builtins arguments.
459 int argc = incoming->length() + BuiltinArguments::kNumExtraArgsWithReceiver; 437 int argc = incoming->length() + BuiltinArguments::kNumExtraArgsWithReceiver;
460 BuiltinArguments caller_args(argc, incoming->arguments() + 1); 438 BuiltinArguments caller_args(argc, incoming->arguments() + 1);
461 return DoFunctionBind(isolate, caller_args); 439 return DoFunctionBind(isolate, caller_args);
462 } 440 }
463 441
464 // ES6 section 19.2.3.5 Function.prototype.toString ( ) 442 // ES6 section 19.2.3.5 Function.prototype.toString ( )
465 BUILTIN(FunctionPrototypeToString) { 443 BUILTIN(FunctionPrototypeToString) {
466 HandleScope scope(isolate); 444 HandleScope scope(isolate);
467 Handle<Object> receiver = args.receiver(); 445 Handle<Object> receiver = args.receiver();
468 if (receiver->IsJSBoundFunction()) { 446 if (receiver->IsJSBoundFunction()) {
469 return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver)); 447 return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver));
470 } else if (receiver->IsJSFunction()) { 448 } else if (receiver->IsJSFunction()) {
471 return *JSFunction::ToString(Handle<JSFunction>::cast(receiver)); 449 return *JSFunction::ToString(Handle<JSFunction>::cast(receiver));
472 } 450 }
473 THROW_NEW_ERROR_RETURN_FAILURE( 451 THROW_NEW_ERROR_RETURN_FAILURE(
474 isolate, NewTypeError(MessageTemplate::kNotGeneric, 452 isolate, NewTypeError(MessageTemplate::kNotGeneric,
475 isolate->factory()->NewStringFromAsciiChecked( 453 isolate->factory()->NewStringFromAsciiChecked(
476 "Function.prototype.toString"))); 454 "Function.prototype.toString")));
477 } 455 }
478 456
479 // ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V ) 457 // ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V )
480 void Builtins::Generate_FunctionPrototypeHasInstance( 458 TF_BUILTIN(FunctionPrototypeHasInstance, CodeStubAssembler) {
481 compiler::CodeAssemblerState* state) { 459 Node* f = Parameter(0);
482 using compiler::Node; 460 Node* v = Parameter(1);
483 CodeStubAssembler assembler(state); 461 Node* context = Parameter(4);
484 462 Node* result = OrdinaryHasInstance(context, f, v);
485 Node* f = assembler.Parameter(0); 463 Return(result);
486 Node* v = assembler.Parameter(1);
487 Node* context = assembler.Parameter(4);
488 Node* result = assembler.OrdinaryHasInstance(context, f, v);
489 assembler.Return(result);
490 } 464 }
491 465
492 } // namespace internal 466 } // namespace internal
493 } // namespace v8 467 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-date.cc ('k') | src/builtins/builtins-global.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698